95 lines
3.5 KiB
C#
95 lines
3.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Animation;
|
|
using System.Windows.Threading;
|
|
|
|
namespace Ticker.Animation
|
|
{
|
|
public class Ticker<T> where T : FrameworkElement
|
|
{
|
|
private static int DISPLAY_TIMER_SPEED_SECONDS=40; // This is the speed used to traverse the display from right to left
|
|
private static int DISPLAY_TIMER_INTERVAL_MILLISECONDS=1000; // This is the interval of time between displaying successive items
|
|
private readonly DispatcherTimer displayTimer=new DispatcherTimer(DispatcherPriority.Normal); // new DispatcherTimer();
|
|
public EventHandler<ItemEventArgs<T>> ItemDisplayed;
|
|
public Ticker(Panel container)
|
|
{
|
|
SeperatorSize = 25;
|
|
Container = container;
|
|
Container.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
|
|
Container.Arrange(new Rect(Container.DesiredSize));
|
|
Speed = new TimeSpan(0, 0, 0, DISPLAY_TIMER_SPEED_SECONDS);
|
|
Items = new Queue<T>();
|
|
displayTimer.Tick += displayTimer_Tick;
|
|
displayTimer.Start();
|
|
IsRunning = true;
|
|
}
|
|
public virtual void Dispose()
|
|
{
|
|
Stop();
|
|
}
|
|
public bool IsRunning { get; set; }
|
|
public void Stop()
|
|
{
|
|
if(!IsRunning)return;
|
|
if(null!=displayTimer)displayTimer.Stop();
|
|
IsRunning = false;
|
|
}
|
|
public void Start()
|
|
{
|
|
if(IsRunning)return;
|
|
if(null==displayTimer)return;
|
|
displayTimer.Start();
|
|
displayTimer.Interval = new TimeSpan(0,0,0,0,DISPLAY_TIMER_INTERVAL_MILLISECONDS);
|
|
IsRunning = true;
|
|
}
|
|
public double SeperatorSize { get; set; }
|
|
public TimeSpan Speed { get; set; }
|
|
public Queue<T> Items { get; set; }
|
|
public Panel Container { get; private set; }
|
|
private void displayTimer_Tick(object sender, EventArgs e)
|
|
{
|
|
DisplayNextItem();
|
|
}
|
|
private void DisplayNextItem()
|
|
{
|
|
if (Items.Count == 0)return;
|
|
T item = Items.Dequeue();
|
|
Container.Children.Add(item);
|
|
AnimateMove(item);
|
|
if (ItemDisplayed != null) ItemDisplayed(this, new ItemEventArgs<T>(item));
|
|
}
|
|
private void AnimateMove(FrameworkElement e)
|
|
{
|
|
e.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
|
|
e.Arrange(new Rect(e.DesiredSize));
|
|
double from = Container.ActualWidth;
|
|
double to = -500;
|
|
int unitsPerSec = Convert.ToInt32(Math.Abs(from - to)/Speed.TotalSeconds);
|
|
int nextFire = Convert.ToInt32((e.ActualWidth + SeperatorSize)/unitsPerSec);
|
|
displayTimer.Stop();
|
|
displayTimer.Interval = new TimeSpan(0, 0, nextFire);
|
|
// displayTimer.Dispatcher.Thread.Priority=ThreadPriority.AboveNormal;
|
|
displayTimer.Start();
|
|
TaggedDoubleAnimation animation = new TaggedDoubleAnimation();
|
|
animation.From = from;
|
|
animation.To = to;
|
|
animation.Duration = new Duration(Speed);
|
|
animation.TargetElement = e;
|
|
animation.Completed += ani_Completed;
|
|
TranslateTransform translateTransform = new TranslateTransform();
|
|
e.RenderTransform = translateTransform;
|
|
translateTransform.BeginAnimation(TranslateTransform.XProperty, animation, HandoffBehavior.Compose);
|
|
}
|
|
private void ani_Completed(object sender, EventArgs e)
|
|
{
|
|
Clock clock = (Clock) sender;
|
|
TaggedDoubleAnimation animation = (TaggedDoubleAnimation) clock.Timeline;
|
|
FrameworkElement element = animation.TargetElement;
|
|
Container.Children.Remove(element);
|
|
}
|
|
}
|
|
} |