using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Timers; using System.ComponentModel; using System.Diagnostics; namespace Implab.Fx { public delegate void AnimationStep(T target, int elapsed, int duration); public class Animation where TArg: class { int m_duration; int m_delay; int m_elapsed; int m_prevTicks; TArg m_arg; ISynchronizeInvoke m_syncronizationObject; public event AnimationStep Step; Promise m_promise; public Animation(TArg target, int duration, int delay) { if (duration <= 0) throw new ArgumentOutOfRangeException("duration"); if (delay <= 0) throw new ArgumentOutOfRangeException("delay"); m_arg = target; m_syncronizationObject = target as ISynchronizeInvoke; m_duration = duration; m_delay = delay; m_promise = new Promise(); } public Animation(TArg target) : this(target, 500, 30) { } public TArg Traget { get { return m_arg; } } public Promise Play() { var timer = new Timer(m_delay); timer.AutoReset = true; timer.SynchronizingObject = m_syncronizationObject; timer.Elapsed += new ElapsedEventHandler(timer_Elapsed); m_prevTicks = Environment.TickCount; timer.Start(); return m_promise; } void timer_Elapsed(object sender, ElapsedEventArgs args) { var timer = sender as Timer; var dt = Environment.TickCount - m_prevTicks; m_prevTicks = Environment.TickCount; m_elapsed += dt; if (m_elapsed > m_duration) m_elapsed = m_duration; try { var handler = Step; if (handler != null) handler(m_arg, m_elapsed, m_duration); } catch (Exception e) { Trace.TraceError(e.ToString()); } if (m_elapsed < m_duration) timer.Start(); else { timer.Dispose(); m_promise.Resolve(m_arg); } } } }