diff --git a/samples/RenderDemo/Pages/TransitionsPage.xaml b/samples/RenderDemo/Pages/TransitionsPage.xaml index ce5db380c0..1985074b0f 100644 --- a/samples/RenderDemo/Pages/TransitionsPage.xaml +++ b/samples/RenderDemo/Pages/TransitionsPage.xaml @@ -145,7 +145,7 @@ + + + + @@ -181,6 +201,7 @@ + diff --git a/src/Avalonia.Visuals/Animation/Transitions/BrushTransition.cs b/src/Avalonia.Visuals/Animation/Transitions/BrushTransition.cs index 0f7501e279..8d0b9089f9 100644 --- a/src/Avalonia.Visuals/Animation/Transitions/BrushTransition.cs +++ b/src/Avalonia.Visuals/Animation/Transitions/BrushTransition.cs @@ -1,29 +1,67 @@ using System; using Avalonia.Animation.Animators; +using Avalonia.Animation.Easings; using Avalonia.Media; +#nullable enable + namespace Avalonia.Animation { /// /// Transition class that handles with type. - /// Only values of will correctly transition. + /// Only values of will transition correctly at the moment. /// - public class ISolidColorBrushTransition : Transition + public class BrushTransition : Transition { private static readonly ISolidColorBrushAnimator s_animator = new ISolidColorBrushAnimator(); - public override IObservable DoTransition(IObservable progress, IBrush oldValue, IBrush newValue) + public override IObservable DoTransition(IObservable progress, IBrush? oldValue, IBrush? newValue) + { + var oldSolidColorBrush = TryGetSolidColorBrush(oldValue); + var newSolidColorBrush = TryGetSolidColorBrush(newValue); + + if (oldSolidColorBrush != null && newSolidColorBrush != null) + { + EnsureImmutable(ref oldSolidColorBrush); + EnsureImmutable(ref newSolidColorBrush); + + return new AnimatorTransitionObservable( + s_animator, progress, Easing, oldSolidColorBrush, newSolidColorBrush); + } + + return new IncompatibleTransitionObservable(progress, Easing, oldValue, newValue); + } + + private static void EnsureImmutable(ref ISolidColorBrush brush) + { + brush = (ISolidColorBrush)brush.ToImmutable(); + } + + private static ISolidColorBrush? TryGetSolidColorBrush(IBrush? brush) { - var oldSolidBrush = AsImmutable(oldValue); - var newSolidBrush = AsImmutable(newValue); + if (brush is null) + { + return Brushes.Transparent; + } - return new AnimatorTransitionObservable( - s_animator, progress, Easing, oldSolidBrush, newSolidBrush); + return brush as ISolidColorBrush; } - private static ISolidColorBrush AsImmutable(IBrush brush) + private class IncompatibleTransitionObservable : TransitionObservableBase { - return (ISolidColorBrush)(brush as ISolidColorBrush)?.ToImmutable(); + private readonly IBrush? _from; + private readonly IBrush? _to; + + public IncompatibleTransitionObservable(IObservable progress, Easing easing, IBrush? from, IBrush? to) : base(progress, easing) + { + _from = @from; + _to = to; + } + + protected override IBrush? ProduceValue(double progress) + { + return progress < 0.5 ? _from : _to; + } } } }