Browse Source

Requested changes.

José Pedro 8 years ago
parent
commit
5cebc7792f
1 changed files with 59 additions and 29 deletions
  1. 59 29
      src/Avalonia.Controls/ProgressBar.cs

+ 59 - 29
src/Avalonia.Controls/ProgressBar.cs

@@ -22,7 +22,7 @@ namespace Avalonia.Controls
             AvaloniaProperty.Register<ProgressBar, Orientation>(nameof(Orientation), Orientation.Horizontal);
 
         private Border _indicator;
-        private IDisposable _indeterminateBindSubscription;
+        private IndeterminateAnimation _indeterminateAnimation;
 
         static ProgressBar()
         {
@@ -30,26 +30,23 @@ namespace Avalonia.Controls
 
             HorizontalAlignmentProperty.OverrideDefaultValue<ProgressBar>(HorizontalAlignment.Left);
             VerticalAlignmentProperty.OverrideDefaultValue<ProgressBar>(VerticalAlignment.Top);
+
+            IsIndeterminateProperty.Changed.AddClassHandler<ProgressBar>(
+                (p, e) => { if (p._indicator != null) p.UpdateIsIndeterminate((bool)e.NewValue); });
+            OrientationProperty.Changed.AddClassHandler<ProgressBar>(
+                (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);
         }
 
         /// <inheritdoc/>
@@ -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> _progressBar;
+            private IDisposable _indeterminateBindSubscription;
+            private TimeSpan _startTime;
+
+            private IndeterminateAnimation(ProgressBar progressBar)
+            {
+                _progressBar = new WeakReference<ProgressBar>(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();
+            }
         }
     }
 }