diff --git a/PCL.Neo/.editorconfig b/PCL.Neo/.editorconfig index ba5847a1..07ebb7d0 100644 --- a/PCL.Neo/.editorconfig +++ b/PCL.Neo/.editorconfig @@ -27,7 +27,7 @@ dotnet_search_reference_assemblies = true # 组织 Using dotnet_separate_import_directive_groups = false dotnet_sort_system_directives_first = false -file_header_template = unset +file_header_template = # this. 和 Me. 首选项 dotnet_style_qualification_for_event = false @@ -219,28 +219,31 @@ dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case dotnet_naming_symbols.interface.applicable_kinds = interface dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.interface.required_modifiers = +dotnet_naming_symbols.interface.required_modifiers = dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.types.required_modifiers = +dotnet_naming_symbols.types.required_modifiers = dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.non_field_members.required_modifiers = +dotnet_naming_symbols.non_field_members.required_modifiers = # 命名样式 -dotnet_naming_style.pascal_case.required_prefix = -dotnet_naming_style.pascal_case.required_suffix = -dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = dotnet_naming_style.pascal_case.capitalization = pascal_case dotnet_naming_style.begins_with_i.required_prefix = I -dotnet_naming_style.begins_with_i.required_suffix = -dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = dotnet_naming_style.begins_with_i.capitalization = pascal_case +# ReSharper properties +resharper_int_align = false + [*.{cs,vb}] end_of_line = crlf dotnet_style_qualification_for_field = false:silent diff --git a/PCL.Neo/Animations/AnimationExtensions.cs b/PCL.Neo/Animations/AnimationExtensions.cs deleted file mode 100644 index 968824f1..00000000 --- a/PCL.Neo/Animations/AnimationExtensions.cs +++ /dev/null @@ -1,253 +0,0 @@ -using Avalonia; -using Avalonia.Animation; -using Avalonia.Animation.Easings; -using Avalonia.Controls; -using Avalonia.Media; -using Avalonia.Styling; -using PCL.Neo.Animations.Easings; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace PCL.Neo.Animations -{ - public static class AnimationExtensions - { - /// - /// 获取指定类型的缓动函数 - /// - public static Easing GetEasing(this EasingType easingType) - { - return easingType switch - { - EasingType.Linear => new LinearEasing(), - EasingType.QuadraticEaseIn => new QuadraticEaseIn(), - EasingType.QuadraticEaseOut => new QuadraticEaseOut(), - EasingType.QuadraticEaseInOut => new QuadraticEaseInOut(), - EasingType.CubicEaseIn => new CubicEaseIn(), - EasingType.CubicEaseOut => new CubicEaseOut(), - EasingType.CubicEaseInOut => new CubicEaseInOut(), - EasingType.QuarticEaseIn => new QuarticEaseIn(), - EasingType.QuarticEaseOut => new QuarticEaseOut(), - EasingType.QuarticEaseInOut => new QuarticEaseInOut(), - EasingType.QuinticEaseIn => new QuinticEaseIn(), - EasingType.QuinticEaseOut => new QuinticEaseOut(), - EasingType.QuinticEaseInOut => new QuinticEaseInOut(), - EasingType.SineEaseIn => new SineEaseIn(), - EasingType.SineEaseOut => new SineEaseOut(), - EasingType.SineEaseInOut => new SineEaseInOut(), - EasingType.CircularEaseIn => new CircularEaseIn(), - EasingType.CircularEaseOut => new CircularEaseOut(), - EasingType.CircularEaseInOut => new CircularEaseInOut(), - EasingType.ExponentialEaseIn => new ExponentialEaseIn(), - EasingType.ExponentialEaseOut => new ExponentialEaseOut(), - EasingType.ExponentialEaseInOut => new ExponentialEaseInOut(), - EasingType.ElasticEaseIn => new ElasticEaseIn(), - EasingType.ElasticEaseOut => new ElasticEaseOut(), - EasingType.ElasticEaseInOut => new ElasticEaseInOut(), - EasingType.BackEaseIn => new BackEaseIn(), - EasingType.BackEaseOut => new BackEaseOut(), - EasingType.BackEaseInOut => new BackEaseInOut(), - EasingType.BounceEaseIn => new BounceEaseIn(), - EasingType.BounceEaseOut => new BounceEaseOut(), - EasingType.BounceEaseInOut => new BounceEaseInOut(), - _ => new LinearEasing() - }; - } - - /// - /// 从右侧滑入动画 - /// - public static async Task SlideInFromRightAsync(this Control control, int duration = 300, EasingType easingType = EasingType.CubicEaseOut) - { - if (control == null) return; - - // 保存原始状态 - var originalOpacity = control.Opacity; - var originalTransform = control.RenderTransform; - - // 设置初始状态 - control.Opacity = 0; - control.RenderTransform = new TranslateTransform(100, 0); - - // 等待UI更新 - await Task.Delay(10); - - // 创建不透明度动画 - var opacityAnimation = new Animation - { - Duration = TimeSpan.FromMilliseconds(duration), - FillMode = FillMode.Forward, - Easing = easingType.GetEasing() - }; - - // 使用正确的Setter语法 - var opacityFrame1 = new KeyFrame(); - opacityFrame1.Cue = new Cue(0d); - opacityFrame1.Setters.Add(new Setter(Visual.OpacityProperty, 0d)); - opacityAnimation.Children.Add(opacityFrame1); - - var opacityFrame2 = new KeyFrame(); - opacityFrame2.Cue = new Cue(1d); - opacityFrame2.Setters.Add(new Setter(Visual.OpacityProperty, originalOpacity)); - opacityAnimation.Children.Add(opacityFrame2); - - // 创建位移动画 - var translateAnimation = new Animation - { - Duration = TimeSpan.FromMilliseconds(duration), - FillMode = FillMode.Forward, - Easing = easingType.GetEasing() - }; - - var translateFrame1 = new KeyFrame(); - translateFrame1.Cue = new Cue(0d); - translateFrame1.Setters.Add(new Setter(Visual.RenderTransformProperty, new TranslateTransform(100, 0))); - translateAnimation.Children.Add(translateFrame1); - - var translateFrame2 = new KeyFrame(); - translateFrame2.Cue = new Cue(1d); - translateFrame2.Setters.Add(new Setter(Visual.RenderTransformProperty, originalTransform ?? new TranslateTransform(0, 0))); - translateAnimation.Children.Add(translateFrame2); - - // 执行动画 - await opacityAnimation.RunAsync(control); - await translateAnimation.RunAsync(control); - } - - /// - /// 从左侧滑入动画 - /// - public static async Task SlideInFromLeftAsync(this Control control, int duration = 300, EasingType easingType = EasingType.CubicEaseOut) - { - if (control == null) return; - - // 保存原始状态 - var originalOpacity = control.Opacity; - var originalTransform = control.RenderTransform; - - // 设置初始状态 - control.Opacity = 0; - control.RenderTransform = new TranslateTransform(-100, 0); - - // 等待UI更新 - await Task.Delay(10); - - // 创建不透明度动画 - var opacityAnimation = new Animation - { - Duration = TimeSpan.FromMilliseconds(duration), - FillMode = FillMode.Forward, - Easing = easingType.GetEasing() - }; - - var opacityFrame1 = new KeyFrame(); - opacityFrame1.Cue = new Cue(0d); - opacityFrame1.Setters.Add(new Setter(Visual.OpacityProperty, 0d)); - opacityAnimation.Children.Add(opacityFrame1); - - var opacityFrame2 = new KeyFrame(); - opacityFrame2.Cue = new Cue(1d); - opacityFrame2.Setters.Add(new Setter(Visual.OpacityProperty, originalOpacity)); - opacityAnimation.Children.Add(opacityFrame2); - - // 创建位移动画 - var translateAnimation = new Animation - { - Duration = TimeSpan.FromMilliseconds(duration), - FillMode = FillMode.Forward, - Easing = easingType.GetEasing() - }; - - var translateFrame1 = new KeyFrame(); - translateFrame1.Cue = new Cue(0d); - translateFrame1.Setters.Add(new Setter(Visual.RenderTransformProperty, new TranslateTransform(-100, 0))); - translateAnimation.Children.Add(translateFrame1); - - var translateFrame2 = new KeyFrame(); - translateFrame2.Cue = new Cue(1d); - translateFrame2.Setters.Add(new Setter(Visual.RenderTransformProperty, originalTransform ?? new TranslateTransform(0, 0))); - translateAnimation.Children.Add(translateFrame2); - - // 执行动画 - await opacityAnimation.RunAsync(control); - await translateAnimation.RunAsync(control); - } - - /// - /// 淡入动画 - /// - public static async Task FadeInAsync(this Control control, int duration = 300, EasingType easingType = EasingType.CubicEaseOut) - { - if (control == null) return; - - // 保存原始状态 - var originalOpacity = control.Opacity; - - // 设置初始状态 - control.Opacity = 0; - - // 等待UI更新 - await Task.Delay(10); - - // 创建不透明度动画 - var opacityAnimation = new Animation - { - Duration = TimeSpan.FromMilliseconds(duration), - FillMode = FillMode.Forward, - Easing = easingType.GetEasing() - }; - - var opacityFrame1 = new KeyFrame(); - opacityFrame1.Cue = new Cue(0d); - opacityFrame1.Setters.Add(new Setter(Visual.OpacityProperty, 0d)); - opacityAnimation.Children.Add(opacityFrame1); - - var opacityFrame2 = new KeyFrame(); - opacityFrame2.Cue = new Cue(1d); - opacityFrame2.Setters.Add(new Setter(Visual.OpacityProperty, originalOpacity)); - opacityAnimation.Children.Add(opacityFrame2); - - // 执行动画 - await opacityAnimation.RunAsync(control); - } - - /// - /// 淡出动画 - /// - public static async Task FadeOutAsync(this Control control, int duration = 300, EasingType easingType = EasingType.CubicEaseOut) - { - if (control == null) return; - - // 保存原始状态 - var originalOpacity = control.Opacity; - - // 等待UI更新 - await Task.Delay(10); - - // 创建不透明度动画 - var opacityAnimation = new Animation - { - Duration = TimeSpan.FromMilliseconds(duration), - FillMode = FillMode.Forward, - Easing = easingType.GetEasing() - }; - - var opacityFrame1 = new KeyFrame(); - opacityFrame1.Cue = new Cue(0d); - opacityFrame1.Setters.Add(new Setter(Visual.OpacityProperty, originalOpacity)); - opacityAnimation.Children.Add(opacityFrame1); - - var opacityFrame2 = new KeyFrame(); - opacityFrame2.Cue = new Cue(1d); - opacityFrame2.Setters.Add(new Setter(Visual.OpacityProperty, 0d)); - opacityAnimation.Children.Add(opacityFrame2); - - // 执行动画 - await opacityAnimation.RunAsync(control); - - // 设置最终状态 - control.Opacity = 0; - } - } -} \ No newline at end of file diff --git a/PCL.Neo/Animations/BaseAnimation.cs b/PCL.Neo/Animations/BaseAnimation.cs new file mode 100644 index 00000000..43cd7e25 --- /dev/null +++ b/PCL.Neo/Animations/BaseAnimation.cs @@ -0,0 +1,47 @@ +using Avalonia.Animation; +using Avalonia.Animation.Easings; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace PCL.Neo.Animations +{ + public abstract class BaseAnimation( + Animatable control, + double begin, + double end, + Easing easing, + TimeSpan duration, + TimeSpan delay, + bool wait) + : IAnimation + { + /// + public TimeSpan Delay { get; } = delay; + + public bool Wait { get; } = wait; + + private readonly CancellationTokenSource _cancellationTokenSource = new(); + private Animatable Control { get; } = control; + protected TimeSpan Duration { get; } = duration; + protected double? Begin { get; } = begin; + protected double? End { get; } = end; + protected Easing Easing { get; } = easing; + + + /// + public abstract Animation AnimationBuilder(); + + /// + public async Task RunAsync() + { + await AnimationBuilder().RunAsync(Control, _cancellationTokenSource.Token); + } + + /// + public void Cancel() + { + _cancellationTokenSource.Cancel(); + } + } +} \ No newline at end of file diff --git a/PCL.Neo/Animations/Easings/EasingType.cs b/PCL.Neo/Animations/Easings/EasingType.cs index 26765433..a8f76740 100644 --- a/PCL.Neo/Animations/Easings/EasingType.cs +++ b/PCL.Neo/Animations/Easings/EasingType.cs @@ -34,4 +34,4 @@ public enum EasingType BounceEaseOut, BounceEaseInOut } -} \ No newline at end of file +} \ No newline at end of file diff --git a/PCL.Neo/Animations/Easings/MyBackEaseIn.cs b/PCL.Neo/Animations/Easings/MyBackEaseIn.cs index 52af8dda..1635c9f7 100644 --- a/PCL.Neo/Animations/Easings/MyBackEaseIn.cs +++ b/PCL.Neo/Animations/Easings/MyBackEaseIn.cs @@ -3,14 +3,9 @@ namespace PCL.Neo.Animations.Easings { - public class MyBackEaseIn : Easing + public class MyBackEaseIn(EasePower power = EasePower.Middle) : Easing { - private readonly double p; - - public MyBackEaseIn(EasePower power = EasePower.Middle) - { - p = 3 - (int)power * 0.5; - } + private readonly double p = 3 - (int)power * 0.5; public override double Ease(double progress) { diff --git a/PCL.Neo/Animations/Easings/MyBackEaseOut.cs b/PCL.Neo/Animations/Easings/MyBackEaseOut.cs index f271ad94..47c1f151 100644 --- a/PCL.Neo/Animations/Easings/MyBackEaseOut.cs +++ b/PCL.Neo/Animations/Easings/MyBackEaseOut.cs @@ -3,18 +3,13 @@ namespace PCL.Neo.Animations.Easings { - public class MyBackEaseOut : Easing + public class MyBackEaseOut(EasePower power = EasePower.Middle) : Easing { - private readonly double p; - - public MyBackEaseOut(EasePower power = EasePower.Middle) - { - p = 3 - (int)power * 0.5; - } + private readonly double _p = 3 - (int)power * 0.5; public override double Ease(double progress) { - return 1 - Math.Pow(1 - progress, p) * Math.Cos(1.5 * Math.PI * progress); + return 1 - Math.Pow(1 - progress, _p) * Math.Cos(1.5 * Math.PI * progress); } } } \ No newline at end of file diff --git a/PCL.Neo/Animations/IAnimation.cs b/PCL.Neo/Animations/IAnimation.cs index 2a444652..66228b68 100644 --- a/PCL.Neo/Animations/IAnimation.cs +++ b/PCL.Neo/Animations/IAnimation.cs @@ -1,7 +1,6 @@ -using System.Threading.Tasks; using Avalonia.Animation; -using Avalonia.Animation.Easings; using System; +using System.Threading.Tasks; namespace PCL.Neo.Animations; @@ -10,15 +9,21 @@ public interface IAnimation /// /// 延迟。 /// - TimeSpan Delay { get; set; } + TimeSpan Delay { get; } + + bool Wait { get; } + /// - /// 指示动画是否要等待上一个动画完成后再执行。与 AnimationHelper 搭配使用。 + /// Build the animation /// - bool Wait { get; set; } + /// The animation + public Animation AnimationBuilder(); + /// /// 异步形式执行动画。 /// Task RunAsync(); + /// /// 取消动画。 /// diff --git a/PCL.Neo/Animations/MarginAnimation.cs b/PCL.Neo/Animations/MarginAnimation.cs index 3b2f38e9..c4f59e90 100644 --- a/PCL.Neo/Animations/MarginAnimation.cs +++ b/PCL.Neo/Animations/MarginAnimation.cs @@ -2,79 +2,26 @@ using Avalonia.Animation; using Avalonia.Animation.Easings; using Avalonia.Controls; +using Avalonia.Layout; using Avalonia.Styling; using System; -using System.Threading; -using System.Threading.Tasks; namespace PCL.Neo.Animations { - public class MarginAnimation : IAnimation + /// + /// margin Animation + /// + /// 请自行添加 + public class MarginAnimation( + Animatable control, + double begin, + double end, + Easing easing, + TimeSpan duration, + TimeSpan delay, + bool wait) + : BaseAnimation(control, begin, end, easing, duration, delay, wait) { - private CancellationTokenSource _cancellationTokenSource; - public Animatable Control { get; set; } - public TimeSpan Duration { get; set; } - public TimeSpan Delay { get; set; } - public Thickness? ValueBefore { get; set; } - public Thickness ValueAfter { get; set; } - public Easing Easing { get; set; } - public bool Wait { get; set; } = false; - - public MarginAnimation(Animatable control, Thickness valueAfter) : this( - control, valueAfter, new LinearEasing()) - { - } - public MarginAnimation(Animatable control, Thickness valueAfter, Easing easing) : this( - control, TimeSpan.FromSeconds(1), valueAfter, easing) - { - } - public MarginAnimation(Animatable control, TimeSpan duration, Thickness valueAfter) : this( - control, duration, valueAfter, new LinearEasing()) - { - } - public MarginAnimation(Animatable control, TimeSpan duration, TimeSpan delay, Thickness valueAfter) : this( - control, duration, delay, valueAfter, new LinearEasing()) - { - } - public MarginAnimation(Animatable control, TimeSpan duration, Thickness valueAfter, Easing easing) : this( - control, duration, GetCurrentMargin(control), valueAfter, easing) - { - } - public MarginAnimation(Animatable control, TimeSpan duration, TimeSpan delay, Thickness valueAfter, Easing easing) : this( - control, duration, delay, GetCurrentMargin(control), valueAfter, easing) - { - } - public MarginAnimation(Animatable control, Thickness? valueBefore, Thickness valueAfter) : this( - control, valueBefore, valueAfter, new LinearEasing()) - { - } - public MarginAnimation(Animatable control, Thickness? valueBefore, Thickness valueAfter, Easing easing) : this( - control, TimeSpan.FromSeconds(1), valueBefore, valueAfter, easing) - { - } - public MarginAnimation(Animatable control, TimeSpan duration, Thickness? valueBefore, Thickness valueAfter) : this( - control, duration, valueBefore, valueAfter, new LinearEasing()) - { - } - public MarginAnimation(Animatable control, TimeSpan duration, TimeSpan delay, Thickness? valueBefore, Thickness valueAfter) : this( - control, duration, delay, valueBefore, valueAfter, new LinearEasing()) - { - } - public MarginAnimation(Animatable control, TimeSpan duration, Thickness? valueBefore, Thickness valueAfter, Easing easing) : this( - control, duration, TimeSpan.Zero, valueBefore, valueAfter, easing) - { - } - public MarginAnimation(Animatable control, TimeSpan duration, TimeSpan delay, Thickness? valueBefore, Thickness valueAfter, Easing easing) - { - Control = control; - Duration = duration; - Delay = delay; - ValueBefore = valueBefore; - ValueAfter = valueAfter; - Easing = easing; - _cancellationTokenSource = new CancellationTokenSource(); - } - private static Thickness? GetCurrentMargin(Animatable control) { if (control is Control c) @@ -84,12 +31,10 @@ public MarginAnimation(Animatable control, TimeSpan duration, TimeSpan delay, Th return null; } - public async Task RunAsync() + /// + public override Animation AnimationBuilder() { - if (Control is not Control controlWithMargin) - return; - - var animation = new Animation + return new Animation { Easing = Easing, Duration = Duration, @@ -97,30 +42,10 @@ public async Task RunAsync() FillMode = FillMode.Both, Children = { - new KeyFrame - { - Setters = - { - new Setter(Avalonia.Controls.Control.MarginProperty, ValueBefore) - }, - Cue = new Cue(0d) - }, - new KeyFrame - { - Setters = - { - new Setter(Avalonia.Controls.Control.MarginProperty, ValueAfter) - }, - Cue = new Cue(1d) - } + new KeyFrame { Setters = { new Setter(Layoutable.MarginProperty, Begin) }, Cue = new Cue(0d) }, + new KeyFrame { Setters = { new Setter(Layoutable.MarginProperty, End) }, Cue = new Cue(1d) } } }; - await animation.RunAsync(Control, _cancellationTokenSource.Token); - } - - public void Cancel() - { - _cancellationTokenSource.Cancel(); } } -} \ No newline at end of file +} \ No newline at end of file diff --git a/PCL.Neo/Animations/OpacityAnimation.cs b/PCL.Neo/Animations/OpacityAnimation.cs index c3eb170b..b0acfe71 100644 --- a/PCL.Neo/Animations/OpacityAnimation.cs +++ b/PCL.Neo/Animations/OpacityAnimation.cs @@ -3,80 +3,22 @@ using Avalonia.Animation.Easings; using Avalonia.Styling; using System; -using System.Threading; -using System.Threading.Tasks; namespace PCL.Neo.Animations { - public class OpacityAnimation : IAnimation + public class OpacityAnimation( + Animatable control, + double begin, + double end, + Easing easing, + TimeSpan duration, + TimeSpan delay, + bool wait) + : BaseAnimation(control, begin, end, easing, duration, delay, wait) { - private CancellationTokenSource _cancellationTokenSource; - public Animatable Control { get; set; } - public TimeSpan Duration { get; set; } - public TimeSpan Delay { get; set; } - public double? ValueBefore { get; set; } - public double ValueAfter { get; set; } - public Easing Easing { get; set; } - public bool Wait { get; set; } = false; - - public OpacityAnimation(Animatable control, double valueAfter) : this( - control, valueAfter, new LinearEasing()) - { - } - public OpacityAnimation(Animatable control, double valueAfter, Easing easing) : this( - control, TimeSpan.FromSeconds(1), valueAfter, easing) - { - } - public OpacityAnimation(Animatable control, TimeSpan duration, double valueAfter) : this( - control, duration, valueAfter, new LinearEasing()) - { - } - public OpacityAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double valueAfter) : this( - control, duration, delay, valueAfter, new LinearEasing()) - { - } - public OpacityAnimation(Animatable control, TimeSpan duration, double valueAfter, Easing easing) : this( - control, duration, control.GetValue(Visual.OpacityProperty), valueAfter, easing) - { - } - public OpacityAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double valueAfter, Easing easing) : this( - control, duration, delay, control.GetValue(Visual.OpacityProperty), valueAfter, easing) - { - } - public OpacityAnimation(Animatable control, double? valueBefore, double valueAfter) : this( - control, valueBefore, valueAfter, new LinearEasing()) - { - } - public OpacityAnimation(Animatable control, double? valueBefore, double valueAfter, Easing easing) : this( - control, TimeSpan.FromSeconds(1), valueBefore, valueAfter, easing) - { - } - public OpacityAnimation(Animatable control, TimeSpan duration, double? valueBefore, double valueAfter) : this( - control, duration, valueBefore, valueAfter, new LinearEasing()) - { - } - public OpacityAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double? valueBefore, double valueAfter) : this( - control, duration, delay, valueBefore, valueAfter, new LinearEasing()) - { - } - public OpacityAnimation(Animatable control, TimeSpan duration, double? valueBefore, double valueAfter, Easing easing) : this( - control, duration, TimeSpan.Zero, valueBefore, valueAfter, easing) - { - } - public OpacityAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double? valueBefore, double valueAfter, Easing easing) - { - Control = control; - Duration = duration; - Delay = delay; - ValueBefore = valueBefore; - ValueAfter = valueAfter; - Easing = easing; - _cancellationTokenSource = new CancellationTokenSource(); - } - - public async Task RunAsync() - { - var animation = new Animation + /// + public override Animation AnimationBuilder() => + new() { Easing = Easing, Duration = Duration, @@ -84,30 +26,9 @@ public async Task RunAsync() FillMode = FillMode.Both, Children = { - new KeyFrame - { - Setters = - { - new Setter(Visual.OpacityProperty, ValueBefore) - }, - Cue = new Cue(0d) - }, - new KeyFrame - { - Setters = - { - new Setter(Visual.OpacityProperty, ValueAfter) - }, - Cue = new Cue(1d) - } + new KeyFrame { Setters = { new Setter(Visual.OpacityProperty, Begin) }, Cue = new Cue(0d) }, + new KeyFrame { Setters = { new Setter(Visual.OpacityProperty, End) }, Cue = new Cue(1d) } } }; - await animation.RunAsync(Control, _cancellationTokenSource.Token); - } - - public void Cancel() - { - _cancellationTokenSource.Cancel(); - } } } \ No newline at end of file diff --git a/PCL.Neo/Animations/RotateTransformAngleAnimation.cs b/PCL.Neo/Animations/RotateTransformAngleAnimation.cs index eaac4023..e81d08a9 100644 --- a/PCL.Neo/Animations/RotateTransformAngleAnimation.cs +++ b/PCL.Neo/Animations/RotateTransformAngleAnimation.cs @@ -3,80 +3,22 @@ using Avalonia.Media; using Avalonia.Styling; using System; -using System.Threading; -using System.Threading.Tasks; namespace PCL.Neo.Animations { - public class RotateTransformAngleAnimation : IAnimation + public class RotateTransformAngleAnimation( + Animatable control, + double begin, + double end, + Easing easing, + TimeSpan duration, + TimeSpan delay, + bool wait) + : BaseAnimation(control, begin, end, easing, duration, delay, wait) { - private CancellationTokenSource _cancellationTokenSource; - public Animatable Control { get; set; } - public TimeSpan Duration { get; set; } - public TimeSpan Delay { get; set; } - public double? ValueBefore { get; set; } - public double ValueAfter { get; set; } - public Easing Easing { get; set; } - public bool Wait { get; set; } = false; - - public RotateTransformAngleAnimation(Animatable control, double valueAfter) : this( - control, valueAfter, new LinearEasing()) - { - } - public RotateTransformAngleAnimation(Animatable control, double valueAfter, Easing easing) : this( - control, TimeSpan.FromSeconds(1), valueAfter, easing) - { - } - public RotateTransformAngleAnimation(Animatable control, TimeSpan duration, double valueAfter) : this( - control, duration, valueAfter, new LinearEasing()) - { - } - public RotateTransformAngleAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double valueAfter) : this( - control, duration, delay, valueAfter, new LinearEasing()) - { - } - public RotateTransformAngleAnimation(Animatable control, TimeSpan duration, double valueAfter, Easing easing) : this( - control, duration, control.GetValue(RotateTransform.AngleProperty), valueAfter, easing) - { - } - public RotateTransformAngleAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double valueAfter, Easing easing) : this( - control, duration, delay, control.GetValue(RotateTransform.AngleProperty), valueAfter, easing) - { - } - public RotateTransformAngleAnimation(Animatable control, double? valueBefore, double valueAfter) : this( - control, valueBefore, valueAfter, new LinearEasing()) - { - } - public RotateTransformAngleAnimation(Animatable control, double? valueBefore, double valueAfter, Easing easing) : this( - control, TimeSpan.FromSeconds(1), valueBefore, valueAfter, easing) - { - } - public RotateTransformAngleAnimation(Animatable control, TimeSpan duration, double? valueBefore, double valueAfter) : this( - control, duration, valueBefore, valueAfter, new LinearEasing()) - { - } - public RotateTransformAngleAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double? valueBefore, double valueAfter) : this( - control, duration, delay, valueBefore, valueAfter, new LinearEasing()) - { - } - public RotateTransformAngleAnimation(Animatable control, TimeSpan duration, double? valueBefore, double valueAfter, Easing easing) : this( - control, duration, TimeSpan.Zero, valueBefore, valueAfter, easing) - { - } - public RotateTransformAngleAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double? valueBefore, double valueAfter, Easing easing) - { - Control = control; - Duration = duration; - Delay = delay; - ValueBefore = valueBefore; - ValueAfter = valueAfter; - Easing = easing; - _cancellationTokenSource = new CancellationTokenSource(); - } - - public async Task RunAsync() - { - var animation = new Animation + /// + public override Animation AnimationBuilder() => + new() { Easing = Easing, Duration = Duration, @@ -84,29 +26,9 @@ public async Task RunAsync() FillMode = FillMode.Both, Children = { - new KeyFrame - { - Setters = - { - new Setter(RotateTransform.AngleProperty, ValueBefore) - }, - Cue = new Cue(0d) - }, - new KeyFrame - { - Setters = - { - new Setter(RotateTransform.AngleProperty, ValueAfter) - }, - Cue = new Cue(1d) - } + new KeyFrame { Setters = { new Setter(RotateTransform.AngleProperty, Begin) }, Cue = new Cue(0d) }, + new KeyFrame { Setters = { new Setter(RotateTransform.AngleProperty, End) }, Cue = new Cue(1d) } } }; - await animation.RunAsync(Control, _cancellationTokenSource.Token); - } - public void Cancel() - { - _cancellationTokenSource.Cancel(); - } } } \ No newline at end of file diff --git a/PCL.Neo/Animations/ScaleTransformScaleAnimation.cs b/PCL.Neo/Animations/ScaleTransformScaleAnimation.cs new file mode 100644 index 00000000..c46ba9fd --- /dev/null +++ b/PCL.Neo/Animations/ScaleTransformScaleAnimation.cs @@ -0,0 +1,54 @@ +using Avalonia.Animation; +using Avalonia.Animation.Easings; +using Avalonia.Media; +using Avalonia.Styling; +using System; + +namespace PCL.Neo.Animations +{ + public record ScaleRate(double X, double Y); + + public class ScaleTransformScaleAnimation( + Animatable control, + ScaleRate begin, + ScaleRate end, + Easing easing, + TimeSpan duration, + TimeSpan delay, + bool wait) + : BaseAnimation(control, 0d, 0d, easing, duration, delay, wait) + { + /// + public override Animation AnimationBuilder() + { + return new Animation + { + Easing = Easing, + Duration = Duration, + Delay = Delay, + FillMode = FillMode.Both, + Children = + { + new KeyFrame + { + Setters = + { + new Setter(ScaleTransform.ScaleXProperty, begin.X), + new Setter(ScaleTransform.ScaleYProperty, begin.Y) + }, + Cue = new Cue(0d) + }, + new KeyFrame + { + Setters = + { + new Setter(ScaleTransform.ScaleXProperty, end.X), + new Setter(ScaleTransform.ScaleYProperty, end.Y) + }, + Cue = new Cue(1d) + } + } + }; + } + } +} \ No newline at end of file diff --git a/PCL.Neo/Animations/ScaleTransformScaleXAnimation.cs b/PCL.Neo/Animations/ScaleTransformScaleXAnimation.cs index 08d0fc72..3a7a7946 100644 --- a/PCL.Neo/Animations/ScaleTransformScaleXAnimation.cs +++ b/PCL.Neo/Animations/ScaleTransformScaleXAnimation.cs @@ -3,80 +3,22 @@ using Avalonia.Media; using Avalonia.Styling; using System; -using System.Threading; -using System.Threading.Tasks; namespace PCL.Neo.Animations { - public class ScaleTransformScaleXAnimation : IAnimation + public class ScaleTransformScaleXAnimation( + Animatable control, + double begin, + double end, + Easing easing, + TimeSpan duration, + TimeSpan delay, + bool wait) + : BaseAnimation(control, begin, end, easing, duration, delay, wait) { - private CancellationTokenSource _cancellationTokenSource; - public Animatable Control { get; set; } - public TimeSpan Duration { get; set; } - public TimeSpan Delay { get; set; } - public double? ValueBefore { get; set; } - public double ValueAfter { get; set; } - public Easing Easing { get; set; } - public bool Wait { get; set; } = false; - - public ScaleTransformScaleXAnimation(Animatable control, double valueAfter) : this( - control, valueAfter, new LinearEasing()) - { - } - public ScaleTransformScaleXAnimation(Animatable control, double valueAfter, Easing easing) : this( - control, TimeSpan.FromSeconds(1), valueAfter, easing) - { - } - public ScaleTransformScaleXAnimation(Animatable control, TimeSpan duration, double valueAfter) : this( - control, duration, valueAfter, new LinearEasing()) - { - } - public ScaleTransformScaleXAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double valueAfter) : this( - control, duration, delay, valueAfter, new LinearEasing()) - { - } - public ScaleTransformScaleXAnimation(Animatable control, TimeSpan duration, double valueAfter, Easing easing) : this( - control, duration, control.GetValue(ScaleTransform.ScaleXProperty), valueAfter, easing) - { - } - public ScaleTransformScaleXAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double valueAfter, Easing easing) : this( - control, duration, delay, control.GetValue(ScaleTransform.ScaleXProperty), valueAfter, easing) - { - } - public ScaleTransformScaleXAnimation(Animatable control, double? valueBefore, double valueAfter) : this( - control, valueBefore, valueAfter, new LinearEasing()) - { - } - public ScaleTransformScaleXAnimation(Animatable control, double? valueBefore, double valueAfter, Easing easing) : this( - control, TimeSpan.FromSeconds(1), valueBefore, valueAfter, easing) - { - } - public ScaleTransformScaleXAnimation(Animatable control, TimeSpan duration, double? valueBefore, double valueAfter) : this( - control, duration, valueBefore, valueAfter, new LinearEasing()) - { - } - public ScaleTransformScaleXAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double? valueBefore, double valueAfter) : this( - control, duration, delay, valueBefore, valueAfter, new LinearEasing()) - { - } - public ScaleTransformScaleXAnimation(Animatable control, TimeSpan duration, double? valueBefore, double valueAfter, Easing easing) : this( - control, duration, TimeSpan.Zero, valueBefore, valueAfter, easing) - { - } - public ScaleTransformScaleXAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double? valueBefore, double valueAfter, Easing easing) - { - Control = control; - Duration = duration; - Delay = delay; - ValueBefore = valueBefore; - ValueAfter = valueAfter; - Easing = easing; - _cancellationTokenSource = new CancellationTokenSource(); - } - - public async Task RunAsync() - { - var animation = new Animation + /// + public override Animation AnimationBuilder() => + new() { Easing = Easing, Duration = Duration, @@ -84,29 +26,9 @@ public async Task RunAsync() FillMode = FillMode.Both, Children = { - new KeyFrame - { - Setters = - { - new Setter(ScaleTransform.ScaleXProperty, ValueBefore) - }, - Cue = new Cue(0d) - }, - new KeyFrame - { - Setters = - { - new Setter(ScaleTransform.ScaleXProperty, ValueAfter) - }, - Cue = new Cue(1d) - } + new KeyFrame { Setters = { new Setter(ScaleTransform.ScaleXProperty, Begin) }, Cue = new Cue(0d) }, + new KeyFrame { Setters = { new Setter(ScaleTransform.ScaleXProperty, End) }, Cue = new Cue(1d) } } }; - await animation.RunAsync(Control, _cancellationTokenSource.Token); - } - public void Cancel() - { - _cancellationTokenSource.Cancel(); - } } } \ No newline at end of file diff --git a/PCL.Neo/Animations/ScaleTransformScaleYAnimation.cs b/PCL.Neo/Animations/ScaleTransformScaleYAnimation.cs index 6e91787b..b3853dbb 100644 --- a/PCL.Neo/Animations/ScaleTransformScaleYAnimation.cs +++ b/PCL.Neo/Animations/ScaleTransformScaleYAnimation.cs @@ -3,80 +3,22 @@ using Avalonia.Media; using Avalonia.Styling; using System; -using System.Threading; -using System.Threading.Tasks; namespace PCL.Neo.Animations { - public class ScaleTransformScaleYAnimation : IAnimation + public class ScaleTransformScaleYAnimation( + Animatable control, + double begin, + double end, + Easing easing, + TimeSpan duration, + TimeSpan delay, + bool wait) + : BaseAnimation(control, begin, end, easing, duration, delay, wait) { - private CancellationTokenSource _cancellationTokenSource; - public Animatable Control { get; set; } - public TimeSpan Duration { get; set; } - public TimeSpan Delay { get; set; } - public double? ValueBefore { get; set; } - public double ValueAfter { get; set; } - public Easing Easing { get; set; } - public bool Wait { get; set; } = false; - - public ScaleTransformScaleYAnimation(Animatable control, double valueAfter) : this( - control, valueAfter, new LinearEasing()) - { - } - public ScaleTransformScaleYAnimation(Animatable control, double valueAfter, Easing easing) : this( - control, TimeSpan.FromSeconds(1), valueAfter, easing) - { - } - public ScaleTransformScaleYAnimation(Animatable control, TimeSpan duration, double valueAfter) : this( - control, duration, valueAfter, new LinearEasing()) - { - } - public ScaleTransformScaleYAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double valueAfter) : this( - control, duration, delay, valueAfter, new LinearEasing()) - { - } - public ScaleTransformScaleYAnimation(Animatable control, TimeSpan duration, double valueAfter, Easing easing) : this( - control, duration, control.GetValue(ScaleTransform.ScaleYProperty), valueAfter, easing) - { - } - public ScaleTransformScaleYAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double valueAfter, Easing easing) : this( - control, duration, delay, control.GetValue(ScaleTransform.ScaleYProperty), valueAfter, easing) - { - } - public ScaleTransformScaleYAnimation(Animatable control, double? valueBefore, double valueAfter) : this( - control, valueBefore, valueAfter, new LinearEasing()) - { - } - public ScaleTransformScaleYAnimation(Animatable control, double? valueBefore, double valueAfter, Easing easing) : this( - control, TimeSpan.FromSeconds(1), valueBefore, valueAfter, easing) - { - } - public ScaleTransformScaleYAnimation(Animatable control, TimeSpan duration, double? valueBefore, double valueAfter) : this( - control, duration, valueBefore, valueAfter, new LinearEasing()) - { - } - public ScaleTransformScaleYAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double? valueBefore, double valueAfter) : this( - control, duration, delay, valueBefore, valueAfter, new LinearEasing()) - { - } - public ScaleTransformScaleYAnimation(Animatable control, TimeSpan duration, double? valueBefore, double valueAfter, Easing easing) : this( - control, duration, TimeSpan.Zero, valueBefore, valueAfter, easing) - { - } - public ScaleTransformScaleYAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double? valueBefore, double valueAfter, Easing easing) - { - Control = control; - Duration = duration; - Delay = delay; - ValueBefore = valueBefore; - ValueAfter = valueAfter; - Easing = easing; - _cancellationTokenSource = new CancellationTokenSource(); - } - - public async Task RunAsync() - { - var animation = new Animation + /// + public override Animation AnimationBuilder() => + new() { Easing = Easing, Duration = Duration, @@ -84,29 +26,9 @@ public async Task RunAsync() FillMode = FillMode.Both, Children = { - new KeyFrame - { - Setters = - { - new Setter(ScaleTransform.ScaleYProperty, ValueBefore) - }, - Cue = new Cue(0d) - }, - new KeyFrame - { - Setters = - { - new Setter(ScaleTransform.ScaleYProperty, ValueAfter) - }, - Cue = new Cue(1d) - } + new KeyFrame { Setters = { new Setter(ScaleTransform.ScaleYProperty, Begin) }, Cue = new Cue(0d) }, + new KeyFrame { Setters = { new Setter(ScaleTransform.ScaleYProperty, End) }, Cue = new Cue(1d) } } }; - await animation.RunAsync(Control, _cancellationTokenSource.Token); - } - public void Cancel() - { - _cancellationTokenSource.Cancel(); - } } } \ No newline at end of file diff --git a/PCL.Neo/Animations/TranslateTransformAnimation.cs b/PCL.Neo/Animations/TranslateTransformAnimation.cs new file mode 100644 index 00000000..84105b8f --- /dev/null +++ b/PCL.Neo/Animations/TranslateTransformAnimation.cs @@ -0,0 +1,52 @@ +using Avalonia.Animation; +using Avalonia.Animation.Easings; +using Avalonia.Media; +using Avalonia.Styling; +using System; + +namespace PCL.Neo.Animations +{ + public record Pos(double X, double Y); + + public class TranslateTransformAnimation( + Animatable control, + Pos begin, + Pos end, + Easing easing, + TimeSpan duration, + TimeSpan delay, + bool wait) + : BaseAnimation(control, 0d, 0d, easing, duration, delay, wait) + { + /// + public override Animation AnimationBuilder() => + new() + { + Easing = Easing, + Duration = Duration, + Delay = Delay, + FillMode = FillMode.Both, + Children = + { + new KeyFrame + { + Setters = + { + new Setter(TranslateTransform.XProperty, begin.X), + new Setter(TranslateTransform.YProperty, begin.Y) + }, + Cue = new Cue(0d) + }, + new KeyFrame + { + Setters = + { + new Setter(TranslateTransform.XProperty, end.X), + new Setter(TranslateTransform.YProperty, end.Y) + }, + Cue = new Cue(1d) + } + } + }; + } +} diff --git a/PCL.Neo/Animations/TranslateTransformXAnimation.cs b/PCL.Neo/Animations/TranslateTransformXAnimation.cs index c5269d49..a63055cc 100644 --- a/PCL.Neo/Animations/TranslateTransformXAnimation.cs +++ b/PCL.Neo/Animations/TranslateTransformXAnimation.cs @@ -3,80 +3,22 @@ using Avalonia.Media; using Avalonia.Styling; using System; -using System.Threading; -using System.Threading.Tasks; namespace PCL.Neo.Animations { - public class TranslateTransformXAnimation : IAnimation + public class TranslateTransformXAnimation( + Animatable control, + double begin, + double end, + Easing easing, + TimeSpan duration, + TimeSpan delay, + bool wait) + : BaseAnimation(control, begin, end, easing, duration, delay, wait) { - private CancellationTokenSource _cancellationTokenSource; - public Animatable Control { get; set; } - public TimeSpan Duration { get; set; } - public TimeSpan Delay { get; set; } - public double? ValueBefore { get; set; } - public double ValueAfter { get; set; } - public Easing Easing { get; set; } - public bool Wait { get; set; } = false; - - public TranslateTransformXAnimation(Animatable control, double valueAfter) : this( - control, valueAfter, new LinearEasing()) - { - } - public TranslateTransformXAnimation(Animatable control, double valueAfter, Easing easing) : this( - control, TimeSpan.FromSeconds(1), valueAfter, easing) - { - } - public TranslateTransformXAnimation(Animatable control, TimeSpan duration, double valueAfter) : this( - control, duration, valueAfter, new LinearEasing()) - { - } - public TranslateTransformXAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double valueAfter) : this( - control, duration, delay, valueAfter, new LinearEasing()) - { - } - public TranslateTransformXAnimation(Animatable control, TimeSpan duration, double valueAfter, Easing easing) : this( - control, duration, control.GetValue(TranslateTransform.XProperty), valueAfter, easing) - { - } - public TranslateTransformXAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double valueAfter, Easing easing) : this( - control, duration, delay, control.GetValue(TranslateTransform.XProperty), valueAfter, easing) - { - } - public TranslateTransformXAnimation(Animatable control, double? valueBefore, double valueAfter) : this( - control, valueBefore, valueAfter, new LinearEasing()) - { - } - public TranslateTransformXAnimation(Animatable control, double? valueBefore, double valueAfter, Easing easing) : this( - control, TimeSpan.FromSeconds(1), valueBefore, valueAfter, easing) - { - } - public TranslateTransformXAnimation(Animatable control, TimeSpan duration, double? valueBefore, double valueAfter) : this( - control, duration, valueBefore, valueAfter, new LinearEasing()) - { - } - public TranslateTransformXAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double? valueBefore, double valueAfter) : this( - control, duration, delay, valueBefore, valueAfter, new LinearEasing()) - { - } - public TranslateTransformXAnimation(Animatable control, TimeSpan duration, double? valueBefore, double valueAfter, Easing easing) : this( - control, duration, TimeSpan.Zero, valueBefore, valueAfter, easing) - { - } - public TranslateTransformXAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double? valueBefore, double valueAfter, Easing easing) - { - Control = control; - Duration = duration; - Delay = delay; - ValueBefore = valueBefore; - ValueAfter = valueAfter; - Easing = easing; - _cancellationTokenSource = new CancellationTokenSource(); - } - - public async Task RunAsync() - { - var animation = new Animation + /// + public override Animation AnimationBuilder() => + new() { Easing = Easing, Duration = Duration, @@ -84,29 +26,9 @@ public async Task RunAsync() FillMode = FillMode.Both, Children = { - new KeyFrame - { - Setters = - { - new Setter(TranslateTransform.XProperty, ValueBefore) - }, - Cue = new Cue(0d) - }, - new KeyFrame - { - Setters = - { - new Setter(TranslateTransform.XProperty, ValueAfter) - }, - Cue = new Cue(1d) - } + new KeyFrame { Setters = { new Setter(TranslateTransform.XProperty, Begin) }, Cue = new Cue(0d) }, + new KeyFrame { Setters = { new Setter(TranslateTransform.XProperty, End) }, Cue = new Cue(1d) } } }; - await animation.RunAsync(Control, _cancellationTokenSource.Token); - } - public void Cancel() - { - _cancellationTokenSource.Cancel(); - } } } \ No newline at end of file diff --git a/PCL.Neo/Animations/TranslateTransformYAnimation.cs b/PCL.Neo/Animations/TranslateTransformYAnimation.cs index ab5d016f..3b7740df 100644 --- a/PCL.Neo/Animations/TranslateTransformYAnimation.cs +++ b/PCL.Neo/Animations/TranslateTransformYAnimation.cs @@ -3,80 +3,22 @@ using Avalonia.Media; using Avalonia.Styling; using System; -using System.Threading; -using System.Threading.Tasks; namespace PCL.Neo.Animations { - public class TranslateTransformYAnimation : IAnimation + public class TranslateTransformYAnimation( + Animatable control, + double begin, + double end, + Easing easing, + TimeSpan duration, + TimeSpan delay, + bool wait) + : BaseAnimation(control, begin, end, easing, duration, delay, wait) { - private CancellationTokenSource _cancellationTokenSource; - public Animatable Control { get; set; } - public TimeSpan Duration { get; set; } - public TimeSpan Delay { get; set; } - public double? ValueBefore { get; set; } - public double ValueAfter { get; set; } - public Easing Easing { get; set; } - public bool Wait { get; set; } = false; - - public TranslateTransformYAnimation(Animatable control, double valueAfter) : this( - control, valueAfter, new LinearEasing()) - { - } - public TranslateTransformYAnimation(Animatable control, double valueAfter, Easing easing) : this( - control, TimeSpan.FromSeconds(1), valueAfter, easing) - { - } - public TranslateTransformYAnimation(Animatable control, TimeSpan duration, double valueAfter) : this( - control, duration, valueAfter, new LinearEasing()) - { - } - public TranslateTransformYAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double valueAfter) : this( - control, duration, delay, valueAfter, new LinearEasing()) - { - } - public TranslateTransformYAnimation(Animatable control, TimeSpan duration, double valueAfter, Easing easing) : this( - control, duration, control.GetValue(TranslateTransform.YProperty), valueAfter, easing) - { - } - public TranslateTransformYAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double valueAfter, Easing easing) : this( - control, duration, delay, control.GetValue(TranslateTransform.YProperty), valueAfter, easing) - { - } - public TranslateTransformYAnimation(Animatable control, double? valueBefore, double valueAfter) : this( - control, valueBefore, valueAfter, new LinearEasing()) - { - } - public TranslateTransformYAnimation(Animatable control, double? valueBefore, double valueAfter, Easing easing) : this( - control, TimeSpan.FromSeconds(1), valueBefore, valueAfter, easing) - { - } - public TranslateTransformYAnimation(Animatable control, TimeSpan duration, double? valueBefore, double valueAfter) : this( - control, duration, valueBefore, valueAfter, new LinearEasing()) - { - } - public TranslateTransformYAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double? valueBefore, double valueAfter) : this( - control, duration, delay, valueBefore, valueAfter, new LinearEasing()) - { - } - public TranslateTransformYAnimation(Animatable control, TimeSpan duration, double? valueBefore, double valueAfter, Easing easing) : this( - control, duration, TimeSpan.Zero, valueBefore, valueAfter, easing) - { - } - public TranslateTransformYAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double? valueBefore, double valueAfter, Easing easing) - { - Control = control; - Duration = duration; - Delay = delay; - ValueBefore = valueBefore; - ValueAfter = valueAfter; - Easing = easing; - _cancellationTokenSource = new CancellationTokenSource(); - } - - public async Task RunAsync() - { - var animation = new Animation + /// + public override Animation AnimationBuilder() => + new() { Easing = Easing, Duration = Duration, @@ -84,29 +26,9 @@ public async Task RunAsync() FillMode = FillMode.Both, Children = { - new KeyFrame - { - Setters = - { - new Setter(TranslateTransform.YProperty, ValueBefore) - }, - Cue = new Cue(0d) - }, - new KeyFrame - { - Setters = - { - new Setter(TranslateTransform.YProperty, ValueAfter) - }, - Cue = new Cue(1d) - } + new KeyFrame { Setters = { new Setter(TranslateTransform.YProperty, Begin) }, Cue = new Cue(0d) }, + new KeyFrame { Setters = { new Setter(TranslateTransform.YProperty, End) }, Cue = new Cue(1d) } } }; - await animation.RunAsync(Control, _cancellationTokenSource.Token); - } - public void Cancel() - { - _cancellationTokenSource.Cancel(); - } } } \ No newline at end of file diff --git a/PCL.Neo/Animations/WaitAnimation.cs b/PCL.Neo/Animations/WaitAnimation.cs new file mode 100644 index 00000000..46b0fee4 --- /dev/null +++ b/PCL.Neo/Animations/WaitAnimation.cs @@ -0,0 +1,30 @@ +using Avalonia; +using Avalonia.Animation; +using Avalonia.Animation.Easings; +using Avalonia.Styling; +using System; + +namespace PCL.Neo.Animations; + +public class WaitAnimation( + Animatable control, + double target, + Easing easing, + TimeSpan duration, + TimeSpan delay, + bool wait) : BaseAnimation(control, 0d, target, easing, duration, delay, wait) +{ + /// + public override Animation AnimationBuilder() + { + return new Animation + { + Delay = Delay, + Duration = Duration, + Children = + { + new KeyFrame { Cue = new Cue(0.0d), Setters = { new Setter(Visual.OpacityProperty, End) } } + }, + }; + } +} \ No newline at end of file diff --git a/PCL.Neo/Animations/XAnimation.cs b/PCL.Neo/Animations/XAnimation.cs index 00d4567f..5f03229a 100644 --- a/PCL.Neo/Animations/XAnimation.cs +++ b/PCL.Neo/Animations/XAnimation.cs @@ -2,74 +2,25 @@ using Avalonia.Animation; using Avalonia.Animation.Easings; using Avalonia.Layout; -using Avalonia.Media; using Avalonia.Styling; using System; -using System.Threading; -using System.Threading.Tasks; namespace PCL.Neo.Animations { - public class XAnimation : IAnimation + public class XAnimation( + Animatable control, + Thickness begin, + Thickness end, + Easing easing, + TimeSpan duration, + TimeSpan delay, + bool wait) + : BaseAnimation(control, 0d, 0d, easing, duration, delay, wait) { - private CancellationTokenSource _cancellationTokenSource; - public Animatable Control { get; set; } - public TimeSpan Duration { get; set; } - public TimeSpan Delay { get; set; } - public double Value { get; set; } - public Easing Easing { get; set; } - public bool Wait { get; set; } = false; - - public XAnimation(Animatable control, double value) : this( - control, value, new LinearEasing()) - { - } - public XAnimation(Animatable control, double value, Easing easing) : this( - control, TimeSpan.FromSeconds(1), value, easing) - { - } - public XAnimation(Animatable control, TimeSpan duration, double value) : this( - control, duration, value, new LinearEasing()) - { - } - public XAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double value) : this( - control, duration, delay, value, new LinearEasing()) - { - } - public XAnimation(Animatable control, TimeSpan duration, double value, Easing easing) : this( - control, duration, TimeSpan.Zero, value, easing) + /// + public override Animation AnimationBuilder() { - } - public XAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double value, Easing easing) - { - Control = control; - Duration = duration; - Delay = delay; - Value = value; - Easing = easing; - _cancellationTokenSource = new CancellationTokenSource(); - } - - public async Task RunAsync() - { - var control = (Layoutable)Control; - Thickness marginOriginal = control.Margin; - Thickness margin; - switch (control.HorizontalAlignment) - { - case HorizontalAlignment.Left: - margin = new Thickness(control.Margin.Left + Value, control.Margin.Top, control.Margin.Right, - control.Margin.Bottom); - break; - case HorizontalAlignment.Right: - margin = new Thickness(control.Margin.Left, control.Margin.Top, control.Margin.Right - Value, - control.Margin.Bottom); - break; - default: - margin = control.Margin; - break; - } - var animation = new Animation + return new Animation { Easing = Easing, Duration = Duration, @@ -77,29 +28,10 @@ public async Task RunAsync() FillMode = FillMode.Both, Children = { - new KeyFrame - { - Setters = - { - new Setter(Layoutable.MarginProperty, marginOriginal) - }, - Cue = new Cue(1d) - }, - new KeyFrame - { - Setters = - { - new Setter(Layoutable.MarginProperty, margin) - }, - Cue = new Cue(1d) - } + new KeyFrame { Setters = { new Setter(Layoutable.MarginProperty, begin) }, Cue = new Cue(1d) }, + new KeyFrame { Setters = { new Setter(Layoutable.MarginProperty, end) }, Cue = new Cue(1d) } } }; - await animation.RunAsync(Control, _cancellationTokenSource.Token); - } - public void Cancel() - { - _cancellationTokenSource.Cancel(); } } } \ No newline at end of file diff --git a/PCL.Neo/Animations/YAnimation.cs b/PCL.Neo/Animations/YAnimation.cs index a7ae30ec..a01082e2 100644 --- a/PCL.Neo/Animations/YAnimation.cs +++ b/PCL.Neo/Animations/YAnimation.cs @@ -2,74 +2,25 @@ using Avalonia.Animation; using Avalonia.Animation.Easings; using Avalonia.Layout; -using Avalonia.Media; using Avalonia.Styling; using System; -using System.Threading; -using System.Threading.Tasks; namespace PCL.Neo.Animations { - public class YAnimation : IAnimation + public class YAnimation( + Animatable control, + Thickness begin, + Thickness end, + Easing easing, + TimeSpan duration, + TimeSpan delay, + bool wait) + : BaseAnimation(control, 0d, 0d, easing, duration, delay, wait) { - private CancellationTokenSource _cancellationTokenSource; - public Animatable Control { get; set; } - public TimeSpan Duration { get; set; } - public TimeSpan Delay { get; set; } - public double Value { get; set; } - public Easing Easing { get; set; } - public bool Wait { get; set; } = false; - - public YAnimation(Animatable control, double value) : this( - control, value, new LinearEasing()) - { - } - public YAnimation(Animatable control, double value, Easing easing) : this( - control, TimeSpan.FromSeconds(1), value, easing) - { - } - public YAnimation(Animatable control, TimeSpan duration, double value) : this( - control, duration, value, new LinearEasing()) - { - } - public YAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double value) : this( - control, duration, delay, value, new LinearEasing()) - { - } - public YAnimation(Animatable control, TimeSpan duration, double value, Easing easing) : this( - control, duration, TimeSpan.Zero, value, easing) + /// + public override Animation AnimationBuilder() { - } - public YAnimation(Animatable control, TimeSpan duration, TimeSpan delay, double value, Easing easing) - { - Control = control; - Duration = duration; - Delay = delay; - Value = value; - Easing = easing; - _cancellationTokenSource = new CancellationTokenSource(); - } - - public async Task RunAsync() - { - var control = (Layoutable)Control; - Thickness marginOriginal = control.Margin; - Thickness margin; - switch (control.VerticalAlignment) - { - case VerticalAlignment.Top: - margin = new Thickness(control.Margin.Left, control.Margin.Top + Value, control.Margin.Right, - control.Margin.Bottom); - break; - case VerticalAlignment.Bottom: - margin = new Thickness(control.Margin.Left, control.Margin.Top, control.Margin.Right, - control.Margin.Bottom - Value); - break; - default: - margin = control.Margin; - break; - } - var animation = new Animation + return new Animation { Easing = Easing, Duration = Duration, @@ -77,29 +28,10 @@ public async Task RunAsync() FillMode = FillMode.Both, Children = { - new KeyFrame - { - Setters = - { - new Setter(Layoutable.MarginProperty, marginOriginal) - }, - Cue = new Cue(1d) - }, - new KeyFrame - { - Setters = - { - new Setter(Layoutable.MarginProperty, margin) - }, - Cue = new Cue(1d) - } + new KeyFrame { Setters = { new Setter(Layoutable.MarginProperty, begin) }, Cue = new Cue(1d) }, + new KeyFrame { Setters = { new Setter(Layoutable.MarginProperty, end) }, Cue = new Cue(1d) } } }; - await animation.RunAsync(Control, _cancellationTokenSource.Token); - } - public void Cancel() - { - _cancellationTokenSource.Cancel(); } } } \ No newline at end of file diff --git a/PCL.Neo/App.axaml.cs b/PCL.Neo/App.axaml.cs index 9f536e9c..39337cb0 100644 --- a/PCL.Neo/App.axaml.cs +++ b/PCL.Neo/App.axaml.cs @@ -1,13 +1,13 @@ -using System.Linq; using Avalonia; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Data.Core.Plugins; using Avalonia.Markup.Xaml; +using Avalonia.Platform.Storage; using CommunityToolkit.Mvvm.DependencyInjection; using Microsoft.Extensions.DependencyInjection; -using PCL.Neo.Core.Models; +using PCL.Neo.Helpers; using PCL.Neo.Services; -using PCL.Neo.Core.Models.Minecraft.Java; +using PCL.Neo.Utils; using PCL.Neo.ViewModels; using PCL.Neo.ViewModels.Download; using PCL.Neo.ViewModels.Home; @@ -18,6 +18,7 @@ using PCL.Neo.Core.Service.Accounts; using PCL.Neo.Core.Service.Accounts.MicrosoftAuth; using System; +using System.Linq; using System.Threading.Tasks; using PCL.Neo.ViewModels.Setup; diff --git a/PCL.Neo/Controls/MyButton.axaml.cs b/PCL.Neo/Controls/MyButton.axaml.cs index 639edabf..7d338746 100644 --- a/PCL.Neo/Controls/MyButton.axaml.cs +++ b/PCL.Neo/Controls/MyButton.axaml.cs @@ -2,27 +2,24 @@ using Avalonia.Animation.Easings; using Avalonia.Controls; using Avalonia.Controls.Documents; -using Avalonia.Controls.Metadata; using Avalonia.Controls.Primitives; using Avalonia.Input; using Avalonia.Media; using Avalonia.Metadata; -using PCL.Neo.Animations; using PCL.Neo.Helpers; +using PCL.Neo.Helpers.Animation; using PCL.Neo.Utils; using System; namespace PCL.Neo.Controls; -[PseudoClasses(":normal", ":highlight", ":red")] +[Avalonia.Controls.Metadata.PseudoClasses(":normal", ":highlight", ":red")] public class MyButton : Button { private Border? _panFore; - private AnimationHelper _animation; public MyButton() { - _animation = new(); Inlines = new InlineCollection(); } @@ -43,29 +40,23 @@ protected override async void OnPointerPressed(PointerPressedEventArgs e) { base.OnPointerPressed(e); - if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) + if (!e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) { - _animation.CancelAndClear(); - _animation.Animations.AddRange([ - new ScaleTransformScaleXAnimation(this, TimeSpan.FromMilliseconds(80), 0.955, new CubicEaseOut()), - new ScaleTransformScaleYAnimation(this, TimeSpan.FromMilliseconds(80), 0.955, new CubicEaseOut()) - ]); - await _animation.RunAsync(); + return; } + + await this.Animate().ScaleTo(0.955d, 80, easing: new CubicEaseOut()).RunAsync(); } protected override async void OnPointerReleased(PointerReleasedEventArgs e) { base.OnPointerReleased(e); - if (e.InitialPressMouseButton == MouseButton.Left) + if (e.InitialPressMouseButton != MouseButton.Left) { - _animation.CancelAndClear(); - _animation.Animations.AddRange([ - new ScaleTransformScaleXAnimation(this, TimeSpan.FromMilliseconds(300), 0.955, 1, new QuinticEaseOut()), - new ScaleTransformScaleYAnimation(this, TimeSpan.FromMilliseconds(300), 0.955, 1, new QuinticEaseOut()) - ]); - await _animation.RunAsync(); + return; } + + await this.Animate().ScaleTo(1d, 300, easing: new CubicEaseOut()).RunAsync(); } public int Uuid = CoreUtils.GetUuid(); @@ -147,18 +138,13 @@ private void RefreshColor() if (_panFore is null) return; if (IsEnabled) { - switch (ColorType) + _panFore.BorderBrush = ColorType switch { - case ColorState.Normal: - _panFore.BorderBrush = (IBrush?)Application.Current!.Resources["ColorBrush1"]; - break; - case ColorState.Highlight: - _panFore.BorderBrush = (IBrush?)Application.Current!.Resources["ColorBrush2"]; - break; - case ColorState.Red: - _panFore.BorderBrush = (IBrush?)Application.Current!.Resources["ColorBrushRedDark"]; - break; - } + ColorState.Normal => (IBrush?)Application.Current!.Resources["ColorBrush1"], + ColorState.Highlight => (IBrush?)Application.Current!.Resources["ColorBrush2"], + ColorState.Red => (IBrush?)Application.Current!.Resources["ColorBrushRedDark"], + _ => _panFore.BorderBrush + }; } else { @@ -174,12 +160,17 @@ private void SetPseudoClasses() case ColorState.Normal: PseudoClasses.Set(":normal", true); break; + case ColorState.Highlight: PseudoClasses.Set(":highlight", true); break; + case ColorState.Red: PseudoClasses.Set(":red", true); break; + + default: + throw new ArgumentOutOfRangeException(); } } } \ No newline at end of file diff --git a/PCL.Neo/Controls/MyCard.axaml.cs b/PCL.Neo/Controls/MyCard.axaml.cs index 130118b7..04cf1973 100644 --- a/PCL.Neo/Controls/MyCard.axaml.cs +++ b/PCL.Neo/Controls/MyCard.axaml.cs @@ -1,23 +1,15 @@ using Avalonia; -using Avalonia.Animation; -using Avalonia.Animation.Easings; using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Media; using PCL.Neo.Helpers; -using System; namespace PCL.Neo.Controls { public class MyCard : ContentControl { private Border? _borderMain; - private AnimationHelper _animation; - public MyCard() - { - _animation = new(); - } protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); @@ -27,7 +19,6 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnSizeChanged(SizeChangedEventArgs e) { base.OnSizeChanged(e); - } public static readonly StyledProperty TitleProperty = AvaloniaProperty.Register( @@ -50,7 +41,6 @@ public Geometry Icon private void HeightAnimation() { - } } } \ No newline at end of file diff --git a/PCL.Neo/Controls/MyIconButton.axaml.cs b/PCL.Neo/Controls/MyIconButton.axaml.cs index 1b77a44b..db1d8609 100644 --- a/PCL.Neo/Controls/MyIconButton.axaml.cs +++ b/PCL.Neo/Controls/MyIconButton.axaml.cs @@ -1,4 +1,3 @@ -using System; using Avalonia; using Avalonia.Animation.Easings; using Avalonia.Controls; @@ -6,13 +5,12 @@ using Avalonia.Controls.Primitives; using Avalonia.Controls.Shapes; using Avalonia.Input; -using Avalonia.Interactivity; using Avalonia.Media; -using PCL.Neo.Animations; -using PCL.Neo.Helpers; +using PCL.Neo.Animations.Easings; +using PCL.Neo.Helpers.Animation; using PCL.Neo.Models; using PCL.Neo.Utils; -using System.Threading.Tasks; +using System; namespace PCL.Neo.Controls; @@ -21,7 +19,6 @@ public class MyIconButton : Button { private Path? _pathIcon; private Border? _panBack; - private readonly AnimationHelper _animation = new AnimationHelper(); protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { @@ -41,34 +38,23 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override async void OnPointerPressed(PointerPressedEventArgs e) { base.OnPointerPressed(e); - if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) + if (!e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) { - _animation.CancelAndClear(); - _animation.Animations.AddRange( - [ - new ScaleTransformScaleXAnimation(_panBack!, TimeSpan.FromMilliseconds(400), 0.8d, - new QuarticEaseOut()), - new ScaleTransformScaleYAnimation(_panBack!, TimeSpan.FromMilliseconds(400), 0.8d, new QuarticEaseOut()) - ]); - await _animation.RunAsync(); + return; } + + await this.Animate().ScaleTo(0.8, duration: 400, easing: new QuadraticEaseOut()).RunAsync(); } protected override async void OnPointerReleased(PointerReleasedEventArgs e) { base.OnPointerReleased(e); - if (e.InitialPressMouseButton == MouseButton.Left) + if (e.InitialPressMouseButton != MouseButton.Left) { - _animation.CancelAndClear(); - _animation.Animations.AddRange( - [ - new ScaleTransformScaleXAnimation(_panBack!, TimeSpan.FromMilliseconds(250), 0.8d, 1d, - new BackEaseOut()), - new ScaleTransformScaleYAnimation(_panBack!, TimeSpan.FromMilliseconds(250), 0.8d, 1d, - new BackEaseOut()) - ]); - await _animation.RunAsync(); + return; } + + await this.Animate().ScaleTo(1d, duration: 250, easing: new MyBackEaseOut()).RunAsync(); } public int Uuid = CoreUtils.GetUuid(); @@ -184,24 +170,15 @@ public string EventData private void RefreshColor() { if (_pathIcon is null || _panBack is null) return; - switch (IconTheme) + _pathIcon.Fill = IconTheme switch { - case IconThemes.Color: - _pathIcon.Fill = (SolidColorBrush?)Application.Current!.Resources["ColorBrush5"]; - break; - case IconThemes.White: - _pathIcon.Fill = (SolidColorBrush)new MyColor(234, 242, 254); - break; - case IconThemes.Red: - _pathIcon.Fill = (SolidColorBrush)new MyColor(160, 255, 76, 76); - break; - case IconThemes.Black: - _pathIcon.Fill = (SolidColorBrush)new MyColor(160, 0, 0, 0); - break; - case IconThemes.Custom: - _pathIcon.Fill = (SolidColorBrush)new MyColor(160, (SolidColorBrush)Foreground); - break; - } + IconThemes.Color => (SolidColorBrush?)Application.Current!.Resources["ColorBrush5"], + IconThemes.White => (SolidColorBrush)new MyColor(234, 242, 254), + IconThemes.Red => (SolidColorBrush)new MyColor(160, 255, 76, 76), + IconThemes.Black => (SolidColorBrush)new MyColor(160, 0, 0, 0), + IconThemes.Custom => (SolidColorBrush)new MyColor(160, (SolidColorBrush)Foreground), + _ => _pathIcon.Fill + }; _panBack.Background = (SolidColorBrush)new MyColor(0, 255, 255, 255); } @@ -213,18 +190,25 @@ private void SetPseudoClass() case IconThemes.Color: PseudoClasses.Set(":color", true); break; + case IconThemes.White: PseudoClasses.Set(":white", true); break; + case IconThemes.Black: PseudoClasses.Set(":black", true); break; + case IconThemes.Red: PseudoClasses.Set(":red", true); break; + case IconThemes.Custom: PseudoClasses.Set(":custom", true); break; + + default: + throw new ArgumentOutOfRangeException(); } } } \ No newline at end of file diff --git a/PCL.Neo/Controls/MyLoading.axaml b/PCL.Neo/Controls/MyLoading.axaml index 84cca215..8a8c8cf9 100644 --- a/PCL.Neo/Controls/MyLoading.axaml +++ b/PCL.Neo/Controls/MyLoading.axaml @@ -5,7 +5,7 @@ diff --git a/PCL.Neo/Controls/MyLoading.axaml.cs b/PCL.Neo/Controls/MyLoading.axaml.cs index fb69f348..34b6d57f 100644 --- a/PCL.Neo/Controls/MyLoading.axaml.cs +++ b/PCL.Neo/Controls/MyLoading.axaml.cs @@ -4,12 +4,9 @@ using Avalonia.Controls.Metadata; using Avalonia.Controls.Primitives; using Avalonia.Controls.Shapes; -using Avalonia.Media; using Avalonia.Threading; -using PCL.Neo.Animations; using PCL.Neo.Animations.Easings; -using PCL.Neo.Helpers; -using System; +using PCL.Neo.Helpers.Animation; using System.Threading.Tasks; namespace PCL.Neo.Controls @@ -17,17 +14,11 @@ namespace PCL.Neo.Controls [PseudoClasses(":loading", ":error")] public class MyLoading : TemplatedControl { - private AnimationHelper _animation; private Path? _pathPickaxe; private Path? _pathError; private Path? _pathLeft; private Path? _pathRight; - private bool _hasErrorOccurred = false; - - public MyLoading() - { - _animation = new(); - } + private bool _hasErrorOccurred; protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { @@ -39,7 +30,7 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e) SetPseudoClasses(); RefreshText(); - StartAnimation(); + RefreshState(); } public static readonly StyledProperty TextProperty = AvaloniaProperty.Register( @@ -85,9 +76,9 @@ public enum LoadingState Error } - public static readonly StyledProperty StateProperty = AvaloniaProperty.Register( - nameof(State), - LoadingState.Loading); + public static readonly StyledProperty StateProperty = + AvaloniaProperty.Register( + nameof(State)); public LoadingState State { @@ -97,114 +88,104 @@ public LoadingState State SetValue(StateProperty, value); SetPseudoClasses(); RefreshText(); + RefreshState(); } } - private void StartAnimation() + private void RefreshState() { - Dispatcher.UIThread.InvokeAsync(async () => + Dispatcher.UIThread.InvokeAsync(() => { - while (true) + var currentState = State; + switch (currentState) { - var currentState = State; - switch (currentState) - { - case LoadingState.Loading: - if (_hasErrorOccurred) - { - await AnimationErrorToLoadingAsync(); - } - _hasErrorOccurred = false; - await AnimationLoadingAsync(); - break; - case LoadingState.Error: - if (!_hasErrorOccurred) - { - _hasErrorOccurred = true; - await AnimationLoadingToErrorAsync(); - break; - } - await Task.Delay(100); - break; - default: - await Task.Delay(100); - break; - } + case LoadingState.Loading: + if (_hasErrorOccurred) + { + AnimationErrorToLoading(); + } + + _hasErrorOccurred = false; + AnimationLoading(); + break; + + case LoadingState.Error: + if (!_hasErrorOccurred) + { + _hasErrorOccurred = true; + AnimationLoadingToError(); + } + + break; } }); } - private async Task AnimationErrorToLoadingAsync() + private void AnimationErrorToLoading() { - _animation.CancelAndClear(); - _animation.Animations.AddRange( - [ - new RotateTransformAngleAnimation(this._pathPickaxe!, TimeSpan.FromMilliseconds(350), 55d, -20d, new MyBackEaseIn(EasePower.Weak)), - new OpacityAnimation(this._pathError!, TimeSpan.FromMilliseconds(100), 0d), - new ScaleTransformScaleXAnimation(this._pathError!, TimeSpan.FromMilliseconds(100), 1d, 0.5d), - new ScaleTransformScaleYAnimation(this._pathError!, TimeSpan.FromMilliseconds(400), 1d, 0.5d) - ]); - await _animation.RunAsync(); + _ = _pathPickaxe!.Animate() + .RotateFromTo(55d, -20d, duration: 350, easing: new MyBackEaseIn(EasePower.Weak)) + .RunAsync(); + + _ = _pathError!.Animate() + .FadeTo(1d, 100) + .ScaleFromTo(1d, 1.2d, 100, wait: true) + .ScaleTo(0.0d, 400, wait: true) + .RunAsync(); } - private async Task AnimationLoadingToErrorAsync() + private void AnimationLoadingToError() { - _animation.CancelAndClear(); - _animation.Animations.AddRange( - [ - new RotateTransformAngleAnimation(this._pathPickaxe!, TimeSpan.FromMilliseconds(900), 55d, new CubicEaseOut()), - new OpacityAnimation(this._pathError!, TimeSpan.FromMilliseconds(300), 1d), - new ScaleTransformScaleXAnimation(this._pathError!, TimeSpan.FromMilliseconds(400), 0.5d, 1d, new MyBackEaseOut()), - new ScaleTransformScaleYAnimation(this._pathError!, TimeSpan.FromMilliseconds(400), 0.5d, 1d, new MyBackEaseOut()) - ]); - await _animation.RunAsync(); + _ = _pathPickaxe!.Animate() + .RotateTo(55d, duration: 900, easing: new CubicEaseOut()) + .RunAsync(); + + _ = _pathError!.Animate() + .FadeTo(1d, 300) + .ScaleTo(1.05d, 400, easing: new MyBackEaseOut(), wait: true) + .ScaleTo(1d, 400, easing: new MyBackEaseOut(), wait: true) + .RunAsync(); } - private async Task AnimationLoadingAsync() + private void AnimationLoading() { // 循环动画,听说这里折磨龙猫很久(doge) - _animation.CancelAndClear(); - _animation.Animations.AddRange( - [ - new RotateTransformAngleAnimation(this._pathPickaxe!, TimeSpan.FromMilliseconds(350), 55d, -20d, new MyBackEaseIn(EasePower.Weak)), - new RotateTransformAngleAnimation(this._pathPickaxe!, TimeSpan.FromMilliseconds(900), 30d, 55d, new ElasticEaseOut()), - new RotateTransformAngleAnimation(this._pathPickaxe!, TimeSpan.FromMilliseconds(180), -20d, 30d), - new OpacityAnimation(this._pathLeft!, TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(50), 1d, 0d), - new XAnimation(this._pathLeft!, TimeSpan.FromMilliseconds(180), -5d, new CubicEaseOut()), - new YAnimation(this._pathLeft!, TimeSpan.FromMilliseconds(180), -6d, new CubicEaseOut()), - new OpacityAnimation(this._pathRight!, TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(50), 1d, 0d), - new XAnimation(this._pathRight!, TimeSpan.FromMilliseconds(180), 5d, new CubicEaseOut()), - new YAnimation(this._pathRight!, TimeSpan.FromMilliseconds(180), -6d, new CubicEaseOut()), - ]); - await _animation.RunAsync(); - this._pathLeft!.Margin = new Thickness(7,41,0,0); - this._pathRight!.Margin = new Thickness(14,41,0,0); + // From Whitecat346: same, really torture for me too + _ = _pathPickaxe!.LoopAnimate() + .RotateFromTo(55d, -20d, duration: 350, easing: new MyBackEaseIn(EasePower.Weak)) + .RotateFromTo(30d, 55d, duration: 900, easing: new ElasticEaseOut()) + .RotateFromTo(-20d, 30d, duration: 180, wait: true) + .RunAsync(); + + + _ = _pathLeft!.LoopAnimate() + .FadeFromTo(1d, 0d, duration: 100, delay: 280, easing: new LinearEasing()) + .MarginXTo(-5d, 180, easing: new CubicEaseOut()) + .MarginYTo(-6d, 180, easing: new CubicEaseOut(), wait: true) + .Wait(1050) + .RunAsync(); + + _ = _pathRight!.LoopAnimate() + .FadeFromTo(1d, 0d, duration: 100, delay: 280, easing: new LinearEasing()) + .MarginXTo(5d, 180, easing: new CubicEaseOut()) + .MarginYTo(-6d, 180, easing: new CubicEaseOut(), wait: true) + .Wait(1050) + .RunAsync(); + + _pathLeft!.Margin = new Thickness(7, 41, 0, 0); + _pathRight!.Margin = new Thickness(14, 41, 0, 0); } private void SetPseudoClasses() { PseudoClasses.Remove(":loading"); PseudoClasses.Remove(":error"); - if (State == LoadingState.Loading) - { - PseudoClasses.Set(":loading", true); - } - else - { - PseudoClasses.Set(":error", true); - } + PseudoClasses.Set(State == LoadingState.Loading ? ":loading" : ":error", true); } private void RefreshText() { - if (State == LoadingState.Loading) - { - this.Text = TextLoading; - } - else - { - this.Text = TextError; - } + this.Text = State == LoadingState.Loading ? TextLoading : TextError; } } } \ No newline at end of file diff --git a/PCL.Neo/Controls/MyMsg/IMessageBox.cs b/PCL.Neo/Controls/MyMsg/IMessageBox.cs index 3275d6e5..93563327 100644 --- a/PCL.Neo/Controls/MyMsg/IMessageBox.cs +++ b/PCL.Neo/Controls/MyMsg/IMessageBox.cs @@ -2,6 +2,5 @@ namespace PCL.Neo.Controls.MyMsg { public interface IMessageBox { - } } \ No newline at end of file diff --git a/PCL.Neo/Controls/MyMsg/MyMsgText.axaml.cs b/PCL.Neo/Controls/MyMsg/MyMsgText.axaml.cs index cec484f6..856c9a85 100644 --- a/PCL.Neo/Controls/MyMsg/MyMsgText.axaml.cs +++ b/PCL.Neo/Controls/MyMsg/MyMsgText.axaml.cs @@ -1,15 +1,12 @@ -using Avalonia; -using Avalonia.Controls; using Avalonia.Controls.Primitives; using PCL.Neo.Helpers; namespace PCL.Neo.Controls.MyMsg { - public class MyMsgText : TemplatedControl , IMessageBox + public class MyMsgText : TemplatedControl, IMessageBox { public MyMsgText(MessageBoxParam param) { - } } } \ No newline at end of file diff --git a/PCL.Neo/Controls/MyRadioButton.axaml.cs b/PCL.Neo/Controls/MyRadioButton.axaml.cs index 38119ea2..85ab5f2e 100644 --- a/PCL.Neo/Controls/MyRadioButton.axaml.cs +++ b/PCL.Neo/Controls/MyRadioButton.axaml.cs @@ -3,7 +3,6 @@ using Avalonia.Controls.Metadata; using Avalonia.Controls.Primitives; using Avalonia.Controls.Shapes; -using Avalonia.Input; using Avalonia.Media; using PCL.Neo.Helpers; using PCL.Neo.Models; @@ -111,14 +110,16 @@ public ColorState ColorType [Obsolete] private void SetCheck() { - if (this.Parent is Panel parent) + if (this.Parent is not Panel parent) { - foreach (var child in parent.Children) + return; + } + + foreach (var child in parent.Children) + { + if (child is MyRadioButton radioButton && radioButton != this) { - if (child is MyRadioButton radioButton && radioButton != this) - { - radioButton.IsChecked = false; - } + radioButton.IsChecked = false; } } } @@ -130,15 +131,23 @@ private void SetPseudoClass() case ColorState.White: PseudoClasses.Set(":white", true); break; + case ColorState.HighLight: PseudoClasses.Set(":highlight", true); break; + + default: + throw new ArgumentOutOfRangeException(); } } private void RefreshColor() { - if (_shapeLogo is null || _labText is null) return; + if (_shapeLogo is null || _labText is null) + { + return; + } + switch (ColorType) { case ColorState.White: @@ -146,7 +155,7 @@ private void RefreshColor() { _panBack!.Background = (SolidColorBrush)new MyColor(255, 255, 255); _shapeLogo.Fill = (IBrush?)Application.Current!.Resources["ColorBrush3"]; - _labText.Foreground = (IBrush?)Application.Current!.Resources["ColorBrush3"]; + _labText.Foreground = (IBrush?)Application.Current.Resources["ColorBrush3"]; } else { @@ -154,7 +163,9 @@ private void RefreshColor() _shapeLogo.Fill = (SolidColorBrush)new MyColor(255, 255, 255); _labText.Foreground = (SolidColorBrush)new MyColor(255, 255, 255); } + break; + case ColorState.HighLight: if (IsChecked!.Value) { @@ -166,9 +177,13 @@ private void RefreshColor() { _panBack!.Background = (SolidColorBrush)ThemeHelper.ColorSemiTransparent; _shapeLogo.Fill = (IBrush?)Application.Current!.Resources["ColorBrush3"]; - _labText.Foreground = (IBrush?)Application.Current!.Resources["ColorBrush3"]; + _labText.Foreground = (IBrush?)Application.Current.Resources["ColorBrush3"]; } + break; + + default: + throw new ArgumentOutOfRangeException(); } } } \ No newline at end of file diff --git a/PCL.Neo/Helpers/Animation/AnimationChain.cs b/PCL.Neo/Helpers/Animation/AnimationChain.cs new file mode 100644 index 00000000..ab9f393f --- /dev/null +++ b/PCL.Neo/Helpers/Animation/AnimationChain.cs @@ -0,0 +1,36 @@ +using Avalonia.Animation; +using System; +using System.Collections.Generic; +using System.Threading; +using IAnimation = PCL.Neo.Animations.IAnimation; + +namespace PCL.Neo.Helpers.Animation +{ + public class AnimationChain(Animatable control) : IDisposable + { + internal Animatable Control { get; } = control; + internal List Animations { get; } = []; + public bool IsComplete { get; internal set; } + + internal bool IsLoop { get; init; } + internal CancellationTokenSource CancellationToken { get; } = new(); + + public void Cancel() + { + CancellationToken.Cancel(); + + foreach (var animation in Animations) + { + animation.Cancel(); + } + + Animations.Clear(); + } + + /// + public void Dispose() + { + CancellationToken.Dispose(); + } + } +} \ No newline at end of file diff --git a/PCL.Neo/Helpers/Animation/AnimationExtensions.cs b/PCL.Neo/Helpers/Animation/AnimationExtensions.cs new file mode 100644 index 00000000..99d5eb0c --- /dev/null +++ b/PCL.Neo/Helpers/Animation/AnimationExtensions.cs @@ -0,0 +1,255 @@ +using Avalonia; +using Avalonia.Animation.Easings; +using Avalonia.Layout; +using Avalonia.Media; +using PCL.Neo.Animations; +using System; + +namespace PCL.Neo.Helpers.Animation +{ + public static class AnimationExtensions + { + #region Helper + + public static AnimationChain Wait(this AnimationChain chain, uint delay) + { + var ani = new WaitAnimation(chain.Control, chain.Control.GetValue(Visual.OpacityProperty), + new LinearEasing(), TimeSpan.Zero, TimeSpan.FromMilliseconds(delay), wait: true); + chain.Animations.Add(ani); + + return chain; + } + + #endregion + + #region Fade + + public static AnimationChain FadeTo(this AnimationChain control, double target, uint duration = 250, + uint delay = 0, + Easing? easing = null, bool wait = false) + { + var beg = control.Control.GetValue(Visual.OpacityProperty); + easing ??= new LinearEasing(); + var ani = new OpacityAnimation(control.Control, beg, target, easing, + TimeSpan.FromMilliseconds(duration), TimeSpan.FromMilliseconds(delay), wait); + control.Animations.Add(ani); + + return control; + } + + + public static AnimationChain FadeFromTo(this AnimationChain control, double begin, double target, + uint duration = 250, + uint delay = 0, + Easing? easing = null, bool wait = false) + { + easing ??= new LinearEasing(); + var ani = new OpacityAnimation(control.Control, begin, target, easing, + TimeSpan.FromMilliseconds(duration), TimeSpan.FromMilliseconds(delay), wait); + + control.Animations.Add(ani); + + return control; + } + + #endregion + + #region Scale + + public static AnimationChain ScaleTo(this AnimationChain control, double target, uint duration = 250, + uint delay = 0, + Easing? easing = null, bool wait = false) + { + var begX = control.Control.GetValue(ScaleTransform.ScaleXProperty); + var begY = control.Control.GetValue(ScaleTransform.ScaleYProperty); + var beg = new ScaleRate(begX, begY); + + easing ??= new LinearEasing(); + + var ani = new ScaleTransformScaleAnimation(control.Control, beg, + new ScaleRate(target, target), easing, + TimeSpan.FromMilliseconds(duration), TimeSpan.FromMilliseconds(delay), wait); + + control.Animations.Add(ani); + return control; + } + + public static AnimationChain ScaleFromTo(this AnimationChain control, double before, double target, + uint duration = 250, + uint delay = 0, + Easing? easing = null, bool wait = false) + { + easing ??= new LinearEasing(); + + var ani = new ScaleTransformScaleAnimation(control.Control, + new ScaleRate(before, before), + new ScaleRate(target, target), easing, + TimeSpan.FromMilliseconds(duration), TimeSpan.FromMilliseconds(delay), wait); + + control.Animations.Add(ani); + return control; + } + + public static AnimationChain ScaleXTo(this AnimationChain control, double target, uint duration = 250, + uint delay = 0, + Easing? easing = null, bool wait = false) + { + var beg = control.Control.GetValue(ScaleTransform.ScaleXProperty); + easing ??= new LinearEasing(); + + var ani = new ScaleTransformScaleXAnimation(control.Control, beg, target, + easing, + TimeSpan.FromMilliseconds(duration), + TimeSpan.FromMilliseconds(delay), wait); + + control.Animations.Add(ani); + + return control; + } + + public static AnimationChain ScaleYTo(this AnimationChain control, double target, uint duration = 250, + uint delay = 0, + Easing? easing = null, bool wait = false) + { + var beg = control.Control.GetValue(ScaleTransform.ScaleYProperty); + easing ??= new LinearEasing(); + + var ani = new ScaleTransformScaleYAnimation(control.Control, beg, target, + easing, + TimeSpan.FromMilliseconds(duration), + TimeSpan.FromMilliseconds(delay), wait); + control.Animations.Add(ani); + + return control; + } + + #endregion + + #region Rotate + + public static AnimationChain RotateTo(this AnimationChain control, double target, uint duration = 250, + uint delay = 0, + Easing? easing = null, bool wait = false) + { + var beg = control.Control.GetValue(RotateTransform.AngleProperty); + easing ??= new LinearEasing(); + + var ani = new RotateTransformAngleAnimation(control.Control, beg, target, + easing, + TimeSpan.FromMilliseconds(duration), TimeSpan.FromMilliseconds(delay), wait); + + control.Animations.Add(ani); + return control; + } + + public static AnimationChain RotateFromTo(this AnimationChain control, double begin, double end, + uint duration = 250, + uint delay = 0, Easing? easing = null, bool wait = false) + { + easing ??= new LinearEasing(); + var ani = new RotateTransformAngleAnimation(control.Control, begin, end, + easing, + TimeSpan.FromMilliseconds(duration), TimeSpan.FromMilliseconds(delay), wait); + control.Animations.Add(ani); + return control; + } + + #endregion + + #region Translate + + public static AnimationChain TranslateTo(this AnimationChain control, Pos target, uint duration = 250, + uint delay = 0, Easing? easing = null, bool wait = false) + { + var begX = control.Control.GetValue(TranslateTransform.XProperty); + var begY = control.Control.GetValue(TranslateTransform.YProperty); + + var beg = new Pos(begX, begY); + + easing ??= new LinearEasing(); + + var ani = new TranslateTransformAnimation(control.Control, beg, target, + easing, + TimeSpan.FromMilliseconds(duration), TimeSpan.FromMilliseconds(delay), wait); + + control.Animations.Add(ani); + return control; + } + + public static AnimationChain TranslateXTo(this AnimationChain control, double target, uint duration = 250, + uint delay = 0, Easing? easing = null, bool wait = false) + { + var beg = control.Control.GetValue(TranslateTransform.XProperty); + easing ??= new LinearEasing(); + var ani = new TranslateTransformXAnimation(control.Control, beg, target, + easing, + TimeSpan.FromMilliseconds(duration), TimeSpan.FromMilliseconds(delay), wait); + control.Animations.Add(ani); + return control; + } + + public static AnimationChain TranslateYTo(this AnimationChain control, double target, uint duration = 250, + uint delay = 0, Easing? easing = null, bool wait = false) + { + var beg = control.Control.GetValue(TranslateTransform.YProperty); + easing ??= new LinearEasing(); + var ani = new TranslateTransformYAnimation(control.Control, beg, target, + easing, + TimeSpan.FromMilliseconds(duration), TimeSpan.FromMilliseconds(delay), wait); + control.Animations.Add(ani); + return control; + } + + #endregion + + #region Margin + + public static AnimationChain MarginXTo(this AnimationChain control, double target, uint duration = 250, + uint delay = 0, Easing? easing = null, bool wait = false) + { + var cot = (Layoutable)control.Control; + + var beg = cot.Margin; + var end = cot.HorizontalAlignment switch + { + HorizontalAlignment.Left => + new Thickness(cot.Margin.Left + target, cot.Margin.Top, cot.Margin.Right, cot.Margin.Bottom), + HorizontalAlignment.Right => + new Thickness(cot.Margin.Left, cot.Margin.Top, cot.Margin.Right - target, cot.Margin.Bottom), + _ => cot.Margin + }; + + easing ??= new LinearEasing(); + + var ani = new XAnimation(control.Control, beg, end, easing, + TimeSpan.FromMilliseconds(duration), TimeSpan.FromMilliseconds(delay), wait); + control.Animations.Add(ani); + return control; + } + + public static AnimationChain MarginYTo(this AnimationChain contorl, double target, uint duration = 250, + uint delay = 0, Easing? easing = null, bool wait = false) + { + var cot = (Layoutable)contorl.Control; + + var beg = cot.Margin; + var end = cot.VerticalAlignment switch + { + VerticalAlignment.Top => new Thickness(cot.Margin.Left, cot.Margin.Top + target, + cot.Margin.Right, cot.Margin.Bottom), + VerticalAlignment.Bottom => new Thickness(cot.Margin.Left, cot.Margin.Top, cot.Margin.Right, + cot.Margin.Bottom - target), + _ => cot.Margin + }; + + easing ??= new LinearEasing(); + + var ani = new XAnimation(contorl.Control, beg, end, easing, + TimeSpan.FromMilliseconds(duration), TimeSpan.FromMilliseconds(delay), wait); + contorl.Animations.Add(ani); + return contorl; + } + + #endregion + } +} \ No newline at end of file diff --git a/PCL.Neo/Helpers/Animation/AnimationHelper.cs b/PCL.Neo/Helpers/Animation/AnimationHelper.cs new file mode 100644 index 00000000..7907d182 --- /dev/null +++ b/PCL.Neo/Helpers/Animation/AnimationHelper.cs @@ -0,0 +1,80 @@ +using Avalonia.Animation; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace PCL.Neo.Helpers.Animation; + +public static class AnimationHelper +{ + private static readonly ConcurrentDictionary InAnimationChains = new(); + + public static AnimationChain Animate(this Animatable control) + { + var ani = new AnimationChain(control) { IsLoop = false }; + var hashCode = control.GetHashCode(); + + // cancel and remove existing animation + if (InAnimationChains.TryGetValue(hashCode, out var existingChain)) + { + existingChain.Cancel(); + InAnimationChains.TryRemove(hashCode, out _); + } + + InAnimationChains.TryAdd(hashCode, ani); + + return ani; + } + + public static AnimationChain LoopAnimate(this Animatable control) + { + var ani = new AnimationChain(control) { IsLoop = true }; + var hashCode = control.GetHashCode(); + + // cancel and remove existing animation + if (InAnimationChains.TryGetValue(hashCode, out var existingChain)) + { + existingChain.Cancel(); + InAnimationChains.TryRemove(hashCode, out _); + } + + InAnimationChains.TryAdd(hashCode, ani); + + return ani; + } + + private static async Task RunAnimation(AnimationChain chain) + { + var tasks = new List(); + do + { + tasks.Clear(); + foreach (var animation in chain.Animations) + { + if (chain.CancellationToken.IsCancellationRequested) + { + break; + } + + var task = animation.RunAsync(); + tasks.Add(task); + if (animation.Wait == false) + { + continue; + } + + await Task.WhenAll(tasks); + tasks.Clear(); + } + } while (chain.CancellationToken.IsCancellationRequested == false && chain.IsLoop); + + chain.IsComplete = true; + } + + public static async Task RunAsync(this AnimationChain chain) + { + await RunAnimation(chain); + + return chain; + } +} \ No newline at end of file diff --git a/PCL.Neo/Helpers/AnimationHelper.cs b/PCL.Neo/Helpers/AnimationHelper.cs deleted file mode 100644 index 7d9135e9..00000000 --- a/PCL.Neo/Helpers/AnimationHelper.cs +++ /dev/null @@ -1,94 +0,0 @@ -using PCL.Neo.Animations; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace PCL.Neo.Helpers; - -/// -/// 动画帮助类,用来同时执行不同动画。 -/// -public class AnimationHelper(List animations) -{ - public List Animations { get; set; } = animations; - public List Tasks { get; } = new List(); - public bool Loop { get; set; } = false; - - public AnimationHelper() : this([]){} - - public void Run() - { - _ = RunAsync(); - } - - public async Task RunAsync() - { - Tasks.Clear(); - - if (Loop) - { - while (true) - { - Tasks.Clear(); - await RunAsyncCore(); - if (!Loop) return; - } - } - - await RunAsyncCore(); - } - - private async Task RunAsyncCore() - { - // 根据 Wait 进行动画分组 - var groupedAnimations = new List>(); - var currentGroup = new List(); - foreach (IAnimation animation in Animations) - { - if (animation.Wait) - { - if (currentGroup.Count > 0) - { - groupedAnimations.Add(new List(currentGroup)); - currentGroup.Clear(); - continue; - } - currentGroup.Add(animation); - } - else - { - currentGroup.Add(animation); - } - } - - if (currentGroup.Count > 0) - { - groupedAnimations.Add(new List(currentGroup)); - } - - currentGroup.Clear(); - - foreach (List list in groupedAnimations) - { - foreach (IAnimation animation in list) - { - Tasks.Add(animation.RunAsync()); - } - - await Task.WhenAll(Tasks); - } - } - - public void Cancel() - { - foreach (IAnimation animation in Animations) - { - animation.Cancel(); - } - } - - public void CancelAndClear() - { - Cancel(); - Animations.Clear(); - } -} \ No newline at end of file diff --git a/PCL.Neo/Helpers/DevelopHelper.cs b/PCL.Neo/Helpers/DevelopHelper.cs index aa7a464a..eae527a6 100644 --- a/PCL.Neo/Helpers/DevelopHelper.cs +++ b/PCL.Neo/Helpers/DevelopHelper.cs @@ -1,5 +1,5 @@ -using System; using PCL.Neo.Utils; +using System; namespace PCL.Neo.Helpers; diff --git a/PCL.Neo/Helpers/ThemeHelper.cs b/PCL.Neo/Helpers/ThemeHelper.cs index 0187f0bb..dd05e08c 100644 --- a/PCL.Neo/Helpers/ThemeHelper.cs +++ b/PCL.Neo/Helpers/ThemeHelper.cs @@ -1,11 +1,9 @@ -using System; using Avalonia; using Avalonia.Media; -using Avalonia.Media.Imaging; -using Avalonia.Platform; using Avalonia.Styling; using PCL.Neo.Models; using PCL.Neo.Views; +using System; namespace PCL.Neo.Helpers; @@ -13,27 +11,27 @@ public class ThemeHelper { private readonly MainWindow _mainWindow; - public static MyColor Color1 { get; set; } = new(52, 61, 74); - public static MyColor Color2 { get; set; } = new(11, 91, 203); - public static MyColor Color3 { get; set; } = new(19, 112, 243); - public static MyColor Color4 { get; set; } = new(72, 144, 245); - public static MyColor Color5 { get; set; } = new(150, 192, 249); - public static MyColor Color6 { get; set; } = new(213, 230, 253); - public static MyColor Color7 { get; set; } = new(222, 236, 253); - public static MyColor Color8 { get; set; } = new(234, 242, 254); - public static MyColor ColorBg0 { get; set; } = new(150, 192, 249); - public static MyColor ColorBg1 { get; set; } = new(190, Color7); - public static MyColor ColorGray1 { get; set; } = new(64, 64, 64); - public static MyColor ColorGray2 { get; set; } = new(115, 115, 115); - public static MyColor ColorGray3 { get; set; } = new(140, 140, 140); - public static MyColor ColorGray4 { get; set; } = new(166, 166, 166); - public static MyColor ColorGray5 { get; set; } = new(204, 204, 204); - public static MyColor ColorGray6 { get; set; } = new(235, 235, 235); - public static MyColor ColorGray7 { get; set; } = new(240, 240, 240); - public static MyColor ColorGray8 { get; set; } = new(245, 245, 245); - public static MyColor ColorSemiTransparent { get; set; } = new(1, Color8); - - private int _colorHue = 50, _colorSat = 65, _colorLightAdjust = 10, _colorHueTopbarDelta = 0; + public static MyColor Color1 { get; } = new(52, 61, 74); + public static MyColor Color2 { get; } = new(11, 91, 203); + public static MyColor Color3 { get; } = new(19, 112, 243); + public static MyColor Color4 { get; } = new(72, 144, 245); + public static MyColor Color5 { get; } = new(150, 192, 249); + public static MyColor Color6 { get; } = new(213, 230, 253); + public static MyColor Color7 { get; } = new(222, 236, 253); + public static MyColor Color8 { get; } = new(234, 242, 254); + public static MyColor ColorBg0 { get; } = new(150, 192, 249); + public static MyColor ColorBg1 { get; } = new(190, Color7); + public static MyColor ColorGray1 { get; } = new(64, 64, 64); + public static MyColor ColorGray2 { get; } = new(115, 115, 115); + public static MyColor ColorGray3 { get; } = new(140, 140, 140); + public static MyColor ColorGray4 { get; } = new(166, 166, 166); + public static MyColor ColorGray5 { get; } = new(204, 204, 204); + public static MyColor ColorGray6 { get; } = new(235, 235, 235); + public static MyColor ColorGray7 { get; } = new(240, 240, 240); + public static MyColor ColorGray8 { get; } = new(245, 245, 245); + public static MyColor ColorSemiTransparent { get; } = new(1, Color8); + + private int _colorHue = 210, _colorSat = 85, _colorLightAdjust = 0, _colorHueTopbarDelta = 0; public ThemeHelper(MainWindow mainWindow) { @@ -47,44 +45,6 @@ public ThemeHelper(MainWindow mainWindow) } public void Refresh(ThemeVariant themeVariant) { - // 主题色 - Color1 = MyColor.FromHsl2(_colorHue, _colorSat * 0.2, 25 + _colorLightAdjust * 0.3); - Color2 = MyColor.FromHsl2(_colorHue, _colorSat, 45 + _colorLightAdjust); - Color3 = MyColor.FromHsl2(_colorHue, _colorSat, 55 + _colorLightAdjust); - Color4 = MyColor.FromHsl2(_colorHue, _colorSat, 65 + _colorLightAdjust); - Color5 = MyColor.FromHsl2(_colorHue, _colorSat, 80 + _colorLightAdjust * 0.4); - Color6 = MyColor.FromHsl2(_colorHue, _colorSat, 91 + _colorLightAdjust * 0.1); - Color7 = MyColor.FromHsl2(_colorHue, _colorSat, 95); - Color7 = MyColor.FromHsl2(_colorHue, _colorSat, 97); - ColorBg0 = Color4 * 0.4 + Color5 * 0.4 + ColorGray4 * 0.2; - ColorBg1 = new MyColor(190, Color7); - ColorSemiTransparent = new MyColor(1, Color8); - - if (Application.Current is not null) - { - Application.Current.Resources["ColorBrush1"] = new SolidColorBrush(Color1); - Application.Current.Resources["ColorBrush2"] = new SolidColorBrush(Color2); - Application.Current.Resources["ColorBrush3"] = new SolidColorBrush(Color3); - Application.Current.Resources["ColorBrush4"] = new SolidColorBrush(Color4); - Application.Current.Resources["ColorBrush5"] = new SolidColorBrush(Color5); - Application.Current.Resources["ColorBrush6"] = new SolidColorBrush(Color6); - Application.Current.Resources["ColorBrush7"] = new SolidColorBrush(Color7); - Application.Current.Resources["ColorBrush8"] = new SolidColorBrush(Color8); - Application.Current.Resources["ColorBrushBg0"] = new SolidColorBrush(ColorBg0); - Application.Current.Resources["ColorBrushBg1"] = new SolidColorBrush(ColorBg1); - - Application.Current.Resources["ColorObject1"] = (Color)Color1; - Application.Current.Resources["ColorObject2"] = (Color)Color2; - Application.Current.Resources["ColorObject3"] = (Color)Color3; - Application.Current.Resources["ColorObject4"] = (Color)Color4; - Application.Current.Resources["ColorObject5"] = (Color)Color5; - Application.Current.Resources["ColorObject6"] = (Color)Color6; - Application.Current.Resources["ColorObject7"] = (Color)Color7; - Application.Current.Resources["ColorObject8"] = (Color)Color8; - Application.Current.Resources["ColorObjectBg0"] = (Color)ColorBg0; - Application.Current.Resources["ColorObjectBg1"] = (Color)ColorBg1; - } - // 标题栏 var brushTitle = new LinearGradientBrush { @@ -110,8 +70,6 @@ public void Refresh(ThemeVariant themeVariant) _mainWindow.NavBackgroundBorder.Background = brushTitle; - _mainWindow.ImgTitle.Source = new Bitmap(AssetLoader.Open(new Uri("avares://PCL.Neo/Assets/Themes/8.png"))); - double lightAdjust = 1; if (themeVariant == ThemeVariant.Light) { diff --git a/PCL.Neo/PCL.Neo.csproj b/PCL.Neo/PCL.Neo.csproj index 6e0a0f1a..852a996a 100644 --- a/PCL.Neo/PCL.Neo.csproj +++ b/PCL.Neo/PCL.Neo.csproj @@ -21,6 +21,14 @@ + + + + + + + + @@ -39,6 +47,7 @@ None All + @@ -75,6 +84,9 @@ + + + diff --git a/PCL.Neo/Program.cs b/PCL.Neo/Program.cs index b4f22669..b28f90e5 100644 --- a/PCL.Neo/Program.cs +++ b/PCL.Neo/Program.cs @@ -1,7 +1,6 @@ -using System; using Avalonia; using Avalonia.Media; -using System.Text; +using System; namespace PCL.Neo { @@ -13,11 +12,11 @@ internal sealed class Program [STAThread] public static void Main(string[] args) { - Console.OutputEncoding = Encoding.UTF8; - BuildAvaloniaApp().StartWithClassicDesktopLifetime(args); // Othre Initialize + Console.OutputEncoding = System.Text.Encoding.UTF8; + Console.InputEncoding = System.Text.Encoding.UTF8; } // Avalonia configuration, don't remove; also used by visual designer. @@ -39,4 +38,4 @@ public static AppBuilder BuildAvaloniaApp() ] }); } -} +} \ No newline at end of file diff --git a/PCL.Neo/Utils/MathUtils.cs b/PCL.Neo/Utils/MathUtils.cs index c06e0ced..db0bb1fc 100644 --- a/PCL.Neo/Utils/MathUtils.cs +++ b/PCL.Neo/Utils/MathUtils.cs @@ -1,6 +1,6 @@ +using PCL.Neo.Models; using System; using System.Linq; -using PCL.Neo.Models; namespace PCL.Neo.Utils; diff --git a/PCL.Neo/ViewLocator.cs b/PCL.Neo/ViewLocator.cs index d921e8bd..e256963e 100644 --- a/PCL.Neo/ViewLocator.cs +++ b/PCL.Neo/ViewLocator.cs @@ -1,7 +1,7 @@ -using System; using Avalonia.Controls; using Avalonia.Controls.Templates; using PCL.Neo.ViewModels; +using System; namespace PCL.Neo; diff --git a/PCL.Neo/ViewModels/DownloadViewModel.cs b/PCL.Neo/ViewModels/DownloadViewModel.cs index 0e8b2dad..5ec4b2ec 100644 --- a/PCL.Neo/ViewModels/DownloadViewModel.cs +++ b/PCL.Neo/ViewModels/DownloadViewModel.cs @@ -1,7 +1,3 @@ -using Avalonia; -using Avalonia.Controls; -using Avalonia.Controls.ApplicationLifetimes; -using Avalonia.Platform.Storage; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using PCL.Neo.Services; @@ -11,27 +7,22 @@ namespace PCL.Neo.ViewModels; [DefaultSubViewModel(typeof(DownloadGameViewModel))] -public partial class DownloadViewModel : ViewModelBase +public partial class DownloadViewModel(NavigationService navigationService) : ViewModelBase { - private readonly INavigationService _navigationService; + public NavigationService NavigationService { get; } = navigationService; [ObservableProperty] private string _message = "I am from DownloadViewModel"; - public DownloadViewModel(INavigationService navigationService) - { - _navigationService = navigationService; - } - [RelayCommand] private async Task NavigateToDownloadGame() { - await _navigationService.GotoAsync(); + await NavigationService.GotoAsync(); } [RelayCommand] private async Task NavigateToDownloadMod() { - await _navigationService.GotoAsync(); + await NavigationService.GotoAsync(); } [RelayCommand] diff --git a/PCL.Neo/ViewModels/Home/VersionManagerViewModel.cs b/PCL.Neo/ViewModels/Home/VersionManagerViewModel.cs index 410bfd69..abfc26d6 100644 --- a/PCL.Neo/ViewModels/Home/VersionManagerViewModel.cs +++ b/PCL.Neo/ViewModels/Home/VersionManagerViewModel.cs @@ -1,17 +1,14 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; +using PCL.Neo.Core.Models.Minecraft.Game; using PCL.Neo.Core.Models.Minecraft.Game.Data; -using PCL.Neo.Models.Minecraft.Game; -using PCL.Neo.Models.Minecraft.Game.Data; using PCL.Neo.Services; -using PCL.Neo.ViewModels; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; using System.Diagnostics; -using PCL.Neo.Core.Models.Minecraft.Game; using System.IO; namespace PCL.Neo.ViewModels.Home; diff --git a/PCL.Neo/ViewModels/HomeViewModel.cs b/PCL.Neo/ViewModels/HomeViewModel.cs index f761599d..da734d2b 100644 --- a/PCL.Neo/ViewModels/HomeViewModel.cs +++ b/PCL.Neo/ViewModels/HomeViewModel.cs @@ -1,14 +1,14 @@ +using Avalonia.Media.Imaging; +using Avalonia.Platform; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using PCL.Neo.Models.User; using PCL.Neo.Services; using PCL.Neo.ViewModels.Home; -using System; -using System.Threading.Tasks; -using Avalonia.Media.Imaging; -using Avalonia.Platform; using SkiaSharp; +using System; using System.IO; +using System.Threading.Tasks; namespace PCL.Neo.ViewModels; @@ -199,4 +199,10 @@ private async Task LoadUserHeadImg() throw; } } + + [RelayCommand] + private void TestButtonAni() + { + Console.WriteLine("Test"); + } } \ No newline at end of file diff --git a/PCL.Neo/ViewModels/LogViewModel.cs b/PCL.Neo/ViewModels/LogViewModel.cs index d4c20fbf..ddb68794 100644 --- a/PCL.Neo/ViewModels/LogViewModel.cs +++ b/PCL.Neo/ViewModels/LogViewModel.cs @@ -25,10 +25,10 @@ public class LogEntry public partial class LogViewModel : ViewModelBase { - private readonly PCL.Neo.Core.Models.Minecraft.Game.GameLauncher _gameLauncher; - private readonly StorageService _storageService; - private ObservableCollection _logEntriesCollection = new ObservableCollection(); - + private readonly GameLauncher _gameLauncher; + private readonly StorageService _storageService; + private ObservableCollection _logEntriesCollection = []; + [ObservableProperty] private ReadOnlyObservableCollection _logEntries; @@ -43,8 +43,8 @@ public partial class LogViewModel : ViewModelBase [ObservableProperty] private string _statusMessage = string.Empty; - - public LogViewModel(PCL.Neo.Core.Models.Minecraft.Game.GameLauncher gameLauncher, StorageService storageService) + + public LogViewModel(GameLauncher gameLauncher, StorageService storageService) { _gameLauncher = gameLauncher; _storageService = storageService; @@ -69,20 +69,17 @@ private void LoadLatestLogFile() if (logFiles.Length > 0) { // 找到最新的日志文件 - string latestLog = logFiles.OrderByDescending(f => File.GetCreationTime(f)).First(); - + string latestLog = logFiles.OrderByDescending(File.GetCreationTime).First(); + // 读取日志文件内容 var lines = File.ReadAllLines(latestLog); foreach (var line in lines) { bool isError = line.Contains("[STDERR]") || line.Contains("[ERROR]"); - string message = line; - + _logEntriesCollection.Add(new LogEntry { - Timestamp = DateTime.Now, - Message = message, - IsError = isError + Timestamp = DateTime.Now, Message = line, IsError = isError }); } diff --git a/PCL.Neo/ViewModels/MainWindowViewModel.cs b/PCL.Neo/ViewModels/MainWindowViewModel.cs index b1b972d7..2e133413 100644 --- a/PCL.Neo/ViewModels/MainWindowViewModel.cs +++ b/PCL.Neo/ViewModels/MainWindowViewModel.cs @@ -2,8 +2,8 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using PCL.Neo.Controls.MyMsg; -using PCL.Neo.Services; using PCL.Neo.Helpers; +using PCL.Neo.Services; using System; using System.Threading.Tasks; diff --git a/PCL.Neo/Views/Home/HomeSubView.axaml b/PCL.Neo/Views/Home/HomeSubView.axaml index e7bdb4a1..f44d765d 100644 --- a/PCL.Neo/Views/Home/HomeSubView.axaml +++ b/PCL.Neo/Views/Home/HomeSubView.axaml @@ -42,6 +42,7 @@ + @@ -185,7 +186,7 @@ - + @@ -213,7 +214,7 @@ - + @@ -261,7 +262,12 @@ - + +