From 5cebc7792f4bb8a1f8aba72ae699647c5227f69d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro?= Date: Mon, 2 Oct 2017 15:58:51 +0100 Subject: [PATCH] Requested changes. --- src/Avalonia.Controls/ProgressBar.cs | 88 +++++++++++++++++++--------- 1 file changed, 59 insertions(+), 29 deletions(-) diff --git a/src/Avalonia.Controls/ProgressBar.cs b/src/Avalonia.Controls/ProgressBar.cs index 015b0a6e96..ea75e7acda 100644 --- a/src/Avalonia.Controls/ProgressBar.cs +++ b/src/Avalonia.Controls/ProgressBar.cs @@ -22,7 +22,7 @@ namespace Avalonia.Controls AvaloniaProperty.Register(nameof(Orientation), Orientation.Horizontal); private Border _indicator; - private IDisposable _indeterminateBindSubscription; + private IndeterminateAnimation _indeterminateAnimation; static ProgressBar() { @@ -30,26 +30,23 @@ namespace Avalonia.Controls HorizontalAlignmentProperty.OverrideDefaultValue(HorizontalAlignment.Left); VerticalAlignmentProperty.OverrideDefaultValue(VerticalAlignment.Top); + + IsIndeterminateProperty.Changed.AddClassHandler( + (p, e) => { if (p._indicator != null) p.UpdateIsIndeterminate((bool)e.NewValue); }); + OrientationProperty.Changed.AddClassHandler( + (p, e) => { if (p._indicator != null) p.UpdateOrientation((Orientation)e.NewValue); }); } public bool IsIndeterminate { get => GetValue(IsIndeterminateProperty); - set - { - SetValue(IsIndeterminateProperty, value); - UpdateIsIndeterminate(value); - } + set => SetValue(IsIndeterminateProperty, value); } public Orientation Orientation { get => GetValue(OrientationProperty); - set - { - SetValue(OrientationProperty, value); - UpdateOrientation(value); - } + set => SetValue(OrientationProperty, value); } /// @@ -115,33 +112,66 @@ namespace Avalonia.Controls private void UpdateIsIndeterminate(bool isIndeterminate) { if (isIndeterminate) + _indeterminateAnimation = IndeterminateAnimation.StartAnimation(this); + else + _indeterminateAnimation?.Dispose(); + } + + private void ValueChanged(AvaloniaPropertyChangedEventArgs e) + { + UpdateIndicator(Bounds.Size); + } + + private class IndeterminateAnimation : IDisposable + { + private WeakReference _progressBar; + private IDisposable _indeterminateBindSubscription; + private TimeSpan _startTime; + + private IndeterminateAnimation(ProgressBar progressBar) + { + _progressBar = new WeakReference(progressBar); + _startTime = Animate.Stopwatch.Elapsed; + _indeterminateBindSubscription = Animate.Timer.TakeWhile(x => (x - _startTime).TotalSeconds <= 4.0) + .Select(GetAnimationRect) + .Finally(() => _startTime = Animate.Stopwatch.Elapsed) + .Repeat() + .Subscribe(AnimationTick); + } + + public static IndeterminateAnimation StartAnimation(ProgressBar progressBar) { - var start = Animate.Stopwatch.Elapsed; + return new IndeterminateAnimation(progressBar); + } - if (Orientation == Orientation.Horizontal) + private Rect GetAnimationRect(TimeSpan time) + { + if (_progressBar.TryGetTarget(out var progressBar)) { - _indeterminateBindSubscription = Animate.Timer.TakeWhile(x => (x - start).TotalSeconds <= 4.0) - .Select(x => new Rect(-_indicator.Width - 5 + (x - start).TotalSeconds / 4.0 * (Bounds.Width + _indicator.Width + 10), 0, _indicator.Bounds.Width, _indicator.Bounds.Height)) - .Finally(() => start = Animate.Stopwatch.Elapsed) - .Repeat() - .Subscribe(x => _indicator.Arrange(x)); + if (progressBar.Orientation == Orientation.Horizontal) + return new Rect(-progressBar._indicator.Width - 5 + (time - _startTime).TotalSeconds / 4.0 * (progressBar.Bounds.Width + progressBar._indicator.Width + 10), 0, progressBar._indicator.Bounds.Width, progressBar._indicator.Bounds.Height); + else + return new Rect(0, progressBar.Bounds.Height + 5 - (time - _startTime).TotalSeconds / 4.0 * (progressBar.Bounds.Height + progressBar._indicator.Height + 10), progressBar._indicator.Bounds.Width, progressBar._indicator.Bounds.Height); } else { - _indeterminateBindSubscription = Animate.Timer.TakeWhile(x => (x - start).TotalSeconds <= 4.0) - .Select(x => new Rect(0, Bounds.Height + 5 - (x - start).TotalSeconds / 4.0 * (Bounds.Height + _indicator.Height + 10), _indicator.Bounds.Width, _indicator.Bounds.Height)) - .Finally(() => start = Animate.Stopwatch.Elapsed) - .Repeat() - .Subscribe(x => _indicator.Arrange(x)); + _indeterminateBindSubscription.Dispose(); + return Rect.Empty; } } - else - _indeterminateBindSubscription?.Dispose(); - } - private void ValueChanged(AvaloniaPropertyChangedEventArgs e) - { - UpdateIndicator(Bounds.Size); + private void AnimationTick(Rect rect) + { + if (_progressBar.TryGetTarget(out var progressBar)) + progressBar._indicator.Arrange(rect); + else + _indeterminateBindSubscription.Dispose(); + } + + public void Dispose() + { + _indeterminateBindSubscription?.Dispose(); + } } } }