Init
This commit is contained in:
162
Animation/FeedManager.cs
Normal file
162
Animation/FeedManager.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Windows.Threading;
|
||||
using Ticker.Models;
|
||||
using Ticker.Helper;
|
||||
|
||||
namespace Ticker.Animation
|
||||
{
|
||||
public class FeedManager
|
||||
{
|
||||
private static int FEED_DEFAULT_INTERVAL_MINUTES=1;
|
||||
private static String FEED_CACHE_FILE_NAME="feedcache.txt";
|
||||
private readonly Dictionary<string, FeedItem> feedItems = new Dictionary<string, FeedItem>();
|
||||
private DispatcherTimer dispatcherTimer = new DispatcherTimer();
|
||||
public event EventHandler<ItemEventArgs<FeedItem>> NewFeedItem;
|
||||
public delegate List<FeedItem> GetFeedItemsEventHandler();
|
||||
public event GetFeedItemsEventHandler FeedSourceEventHandler;
|
||||
private bool stop = false;
|
||||
private bool isInit=true;
|
||||
public FeedManager()
|
||||
{
|
||||
ReadCache();
|
||||
dispatcherTimer.Tick += DispatcherTimer_Tick;
|
||||
dispatcherTimer.Interval = new TimeSpan(0, FEED_DEFAULT_INTERVAL_MINUTES, 0);
|
||||
}
|
||||
public virtual void Dispose()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
public void MarkFeedAsRead(FeedItem item)
|
||||
{
|
||||
if(!feedItems.ContainsKey(item.Guid))return;
|
||||
feedItems[item.Guid].Read = true;
|
||||
WriteCache(item);
|
||||
}
|
||||
public int GetFeedItemCount()
|
||||
{
|
||||
int count=0;
|
||||
lock(feedItems)
|
||||
{
|
||||
if(null==feedItems||0==feedItems.Count)return count;
|
||||
List<FeedItem> feedItemsList=new List<FeedItem>(feedItems.Values);
|
||||
count=(from FeedItem feedItem in feedItemsList where feedItem.Read==false select feedItem).Count();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
private void DispatcherTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
Go();
|
||||
}
|
||||
public int FeedIntervalMinutes
|
||||
{
|
||||
get{return dispatcherTimer.Interval.Minutes;}
|
||||
set{dispatcherTimer.Interval=new TimeSpan(0,value,0);}
|
||||
}
|
||||
public void Start()
|
||||
{
|
||||
stop = false;
|
||||
Go();
|
||||
dispatcherTimer.Start();
|
||||
}
|
||||
public void Stop()
|
||||
{
|
||||
if(stop)return;
|
||||
if(null!=dispatcherTimer)dispatcherTimer.Stop();
|
||||
stop = true;
|
||||
}
|
||||
private void Go()
|
||||
{
|
||||
if(stop)return;
|
||||
if(isInit)
|
||||
{
|
||||
isInit=false;
|
||||
AddOpeningBanner();
|
||||
}
|
||||
ThreadPool.QueueUserWorkItem(LoadFeed,null);
|
||||
}
|
||||
// ***************************************************************************************************************************************************
|
||||
// *************************************************************************** F E E D C A C H E ****************************************************
|
||||
// ***************************************************************************************************************************************************
|
||||
private void ReadCache()
|
||||
{
|
||||
lock(feedItems)
|
||||
{
|
||||
feedItems.Clear();
|
||||
List<FeedItem> cacheItems=FeedSerializer.Deserialize(FEED_CACHE_FILE_NAME);
|
||||
foreach(FeedItem feedItem in cacheItems)
|
||||
{
|
||||
if(!feedItems.ContainsKey(feedItem.Guid))feedItems.Add(feedItem.Guid,feedItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void WriteCache(FeedItem feedItem)
|
||||
{
|
||||
lock(feedItems)
|
||||
{
|
||||
List<FeedItem> cacheItems=new List<FeedItem>(feedItems.Values);
|
||||
FeedSerializer.Serialize(FEED_CACHE_FILE_NAME,DateTime.Today,feedItem);
|
||||
}
|
||||
}
|
||||
// ***************************************************************************************************************************************************
|
||||
private void AddOpeningBanner()
|
||||
{
|
||||
FeedItem feedItem=new FeedItem();
|
||||
DateTime today=DateTime.Now;
|
||||
feedItem.Description="TradeBlotter";
|
||||
feedItem.Title=today.ToLongDateString()+" "+today.ToLongTimeString();
|
||||
feedItem.Guid=today.ToLongTimeString();
|
||||
feedItem.Link="https://www.time.gov/";
|
||||
feedItem.Source="";
|
||||
feedItem.PubDate=today.ToLongDateString();
|
||||
feedItems.Add(feedItem.Guid,feedItem);
|
||||
if (NewFeedItem != null) NewFeedItem(this, new ItemEventArgs<FeedItem>(feedItem));
|
||||
}
|
||||
private void LoadFeed(object state)
|
||||
{
|
||||
try
|
||||
{
|
||||
List<FeedItem> newFeedItems=null;
|
||||
if(null==FeedSourceEventHandler)return;
|
||||
newFeedItems=FeedSourceEventHandler();
|
||||
if(null==newFeedItems||0==newFeedItems.Count)return;
|
||||
foreach (FeedItem item in newFeedItems)
|
||||
{
|
||||
if (stop) return;
|
||||
if (feedItems.ContainsKey(item.Guid)) continue;
|
||||
item.Title = Clean(item.Title).Replace("\r","").Replace("\n","");
|
||||
item.Description = Clean(item.Description);
|
||||
lock (feedItems)
|
||||
{
|
||||
feedItems.Add(item.Guid, item);
|
||||
}
|
||||
if (NewFeedItem != null) NewFeedItem(this, new ItemEventArgs<FeedItem>(item));
|
||||
}
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
private static string Clean(string input)
|
||||
{
|
||||
string output = input.Trim();
|
||||
output = output.Replace("'", "'");
|
||||
output = output.Replace("&", "&");
|
||||
output = output.Replace(""", "\"");
|
||||
output = output.Replace(" ", " ");
|
||||
output = RemoveHTMLTags(output);
|
||||
return output;
|
||||
}
|
||||
private static string RemoveHTMLTags(string text)
|
||||
{
|
||||
string regularExpressionString = "<.+?>";
|
||||
Regex r = new Regex(regularExpressionString, RegexOptions.Singleline);
|
||||
return r.Replace(text, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
14
Animation/ItemEventArgs.cs
Normal file
14
Animation/ItemEventArgs.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace Ticker.Animation
|
||||
{
|
||||
public class ItemEventArgs<T> : EventArgs
|
||||
{
|
||||
public ItemEventArgs(T item)
|
||||
{
|
||||
Item = item;
|
||||
}
|
||||
|
||||
public T Item { get; private set; }
|
||||
}
|
||||
}
|
||||
14
Animation/TaggedDoubleAnimation.cs
Normal file
14
Animation/TaggedDoubleAnimation.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Animation;
|
||||
|
||||
namespace Ticker.Animation
|
||||
{
|
||||
public class TaggedDoubleAnimation : DoubleAnimation
|
||||
{
|
||||
public FrameworkElement TargetElement { get; set; }
|
||||
protected override Freezable CreateInstanceCore()
|
||||
{
|
||||
return new TaggedDoubleAnimation{TargetElement = TargetElement};
|
||||
}
|
||||
}
|
||||
}
|
||||
95
Animation/Ticker.cs
Normal file
95
Animation/Ticker.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user