aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.AnimatedGif/ImageAnimationController.cs
diff options
context:
space:
mode:
authorRoy Ben-Shabat <Roy@Twine-s.com>2018-07-11 12:37:11 +0300
committerRoy Ben-Shabat <Roy@Twine-s.com>2018-07-11 12:37:11 +0300
commitbd49bdcb109a227130d7db6856e659b435d16530 (patch)
treedb55cfdc5dae423ccdba5c7efb1162d33bdcdc48 /Software/Visual_Studio/Tango.AnimatedGif/ImageAnimationController.cs
parentd65e5f1a23374de2872a73034e430e4a70ee4269 (diff)
downloadTango-bd49bdcb109a227130d7db6856e659b435d16530.tar.gz
Tango-bd49bdcb109a227130d7db6856e659b435d16530.zip
Embedded Tango.AnimatedGif !
Diffstat (limited to 'Software/Visual_Studio/Tango.AnimatedGif/ImageAnimationController.cs')
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/ImageAnimationController.cs192
1 files changed, 192 insertions, 0 deletions
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/ImageAnimationController.cs b/Software/Visual_Studio/Tango.AnimatedGif/ImageAnimationController.cs
new file mode 100644
index 000000000..239af9c8b
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/ImageAnimationController.cs
@@ -0,0 +1,192 @@
+using System;
+using System.ComponentModel;
+using System.Linq;
+using System.Windows.Controls;
+using System.Windows.Media.Animation;
+
+namespace Tango.AnimatedGif
+{
+ /// <summary>
+ /// Provides a way to pause, resume or seek a GIF animation.
+ /// </summary>
+ public class ImageAnimationController : IDisposable
+ {
+ private static readonly DependencyPropertyDescriptor _sourceDescriptor;
+
+ static ImageAnimationController()
+ {
+ _sourceDescriptor = DependencyPropertyDescriptor.FromProperty(Image.SourceProperty, typeof (Image));
+ }
+
+ private readonly Image _image;
+ private readonly ObjectAnimationUsingKeyFrames _animation;
+ private readonly AnimationClock _clock;
+ private readonly ClockController _clockController;
+
+
+ public double SpeedRatio
+ {
+ get
+ {
+ return _clockController.SpeedRatio;
+ }
+ set
+ {
+ _clockController.SpeedRatio = value;
+ }
+ }
+
+ internal ImageAnimationController(Image image, ObjectAnimationUsingKeyFrames animation, bool autoStart)
+ {
+ _image = image;
+ _animation = animation;
+ _animation.Completed += AnimationCompleted;
+ _clock = _animation.CreateClock();
+ _clockController = _clock.Controller;
+ _sourceDescriptor.AddValueChanged(image, ImageSourceChanged);
+
+ // ReSharper disable once PossibleNullReferenceException
+ _clockController.Pause();
+
+ _image.ApplyAnimationClock(Image.SourceProperty, _clock);
+
+ if (autoStart)
+ _clockController.Resume();
+ }
+
+ void AnimationCompleted(object sender, EventArgs e)
+ {
+ _image.RaiseEvent(new System.Windows.RoutedEventArgs(ImageBehavior.AnimationCompletedEvent, _image));
+ }
+
+ private void ImageSourceChanged(object sender, EventArgs e)
+ {
+ OnCurrentFrameChanged();
+ }
+
+ /// <summary>
+ /// Returns the number of frames in the image.
+ /// </summary>
+ public int FrameCount
+ {
+ get { return _animation.KeyFrames.Count; }
+ }
+
+ /// <summary>
+ /// Returns the duration of the animation.
+ /// </summary>
+ public TimeSpan Duration
+ {
+ get
+ {
+ return _animation.Duration.HasTimeSpan
+ ? _animation.Duration.TimeSpan
+ : TimeSpan.Zero;
+ }
+ }
+
+ /// <summary>
+ /// Returns a value that indicates whether the animation is paused.
+ /// </summary>
+ public bool IsPaused
+ {
+ get { return _clock.IsPaused; }
+ }
+
+ /// <summary>
+ /// Returns a value that indicates whether the animation is complete.
+ /// </summary>
+ public bool IsComplete
+ {
+ get { return _clock.CurrentState == ClockState.Filling; }
+ }
+
+ /// <summary>
+ /// Seeks the animation to the specified frame index.
+ /// </summary>
+ /// <param name="index">The index of the frame to seek to</param>
+ public void GotoFrame(int index)
+ {
+ var frame = _animation.KeyFrames[index];
+ _clockController.Seek(frame.KeyTime.TimeSpan, TimeSeekOrigin.BeginTime);
+ }
+
+ /// <summary>
+ /// Returns the current frame index.
+ /// </summary>
+ public int CurrentFrame
+ {
+ get
+ {
+ var time = _clock.CurrentTime;
+ var frameAndIndex =
+ _animation.KeyFrames
+ .Cast<ObjectKeyFrame>()
+ .Select((f, i) => new { Time = f.KeyTime.TimeSpan, Index = i })
+ .FirstOrDefault(fi => fi.Time >= time);
+ if (frameAndIndex != null)
+ return frameAndIndex.Index;
+ return -1;
+ }
+ }
+
+ /// <summary>
+ /// Pauses the animation.
+ /// </summary>
+ public void Pause()
+ {
+ _clockController.Pause();
+ }
+
+ /// <summary>
+ /// Starts or resumes the animation. If the animation is complete, it restarts from the beginning.
+ /// </summary>
+ public void Play()
+ {
+ _clockController.Resume();
+ }
+
+ /// <summary>
+ /// Raised when the current frame changes.
+ /// </summary>
+ public event EventHandler CurrentFrameChanged;
+
+ private void OnCurrentFrameChanged()
+ {
+ EventHandler handler = CurrentFrameChanged;
+ if (handler != null) handler(this, EventArgs.Empty);
+ }
+
+ /// <summary>
+ /// Finalizes the current object.
+ /// </summary>
+ ~ImageAnimationController()
+ {
+ Dispose(false);
+ }
+
+ /// <summary>
+ /// Disposes the current object.
+ /// </summary>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Disposes the current object
+ /// </summary>
+ /// <param name="disposing">true to dispose both managed an unmanaged resources, false to dispose only managed resources</param>
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ _image.BeginAnimation(Image.SourceProperty, null);
+ _animation.Completed -= AnimationCompleted;
+ _sourceDescriptor.RemoveValueChanged(_image, ImageSourceChanged);
+ _image.Source = null;
+ }
+ }
+ }
+} \ No newline at end of file