using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Xml;
using TradeIdeas.TIProData;
using TradeIdeas.XML;
namespace TradeIdeas.TIProGUI
{
///
/// Stores all annotations. Knows how to save to and restore from XML.
///
public class ChartAnnotationCache
{
public ChartAnnotationCache() { }
///
/// Adds an annotation to the cache.
///
///
///
public void AddAnnotation(CacheableAnnotation annotation, string symbol)
{
List annotations = new List();
if (_annotations.ContainsKey(symbol))
annotations = _annotations[symbol];
annotations.Add(annotation);
_annotations[symbol] = annotations;
}
///
/// Gets all annotations from the cache that correspond to the symbol and timeframe. Horizontal lines span all timeframes but all other
/// annotation types are specific to a timeframe.
///
///
///
///
public List GetAnnotations(string symbol, ChartTimeframe timeframe)
{
List annotations = new List();
if (_annotations.ContainsKey(symbol))
annotations = _annotations[symbol];
List toReturn = new List();
foreach (CacheableAnnotation annotation in annotations)
{
if (annotation.AnnotationType == AnnotationType.HorizontalLine)
toReturn.Add(annotation);
else if (annotation.ChartTimeframe == timeframe)
toReturn.Add(annotation);
}
return toReturn;
}
///
/// Returns CacheableAnnotation by looking up the original id used when it was created.
///
///
///
/// CacheableAnnotation object.
public CacheableAnnotation GetAnnotation(string id, string symbol)
{
if (_annotations.ContainsKey(symbol))
{
List annotations = _annotations[symbol].Where(x => x.Id == id).ToList();
if (annotations.Count > 0)
return annotations.First();
}
return null;
}
///
/// Removes annotation from cache by first looking it up by id and symbol. If it can't be found this does nothing.
///
///
///
public void RemoveAnnotation(string id, string symbol)
{
if (_annotations.ContainsKey(symbol))
{
List annotations = _annotations[symbol].Where(x => x.Id == id).ToList();
if (annotations.Count > 0)
{
foreach (CacheableAnnotation annotation in annotations)
{
_annotations[symbol].Remove(annotation);
}
}
}
}
///
/// Removes annotation from cache by first looking it up by symbol. If it can't be found this does nothing.
/// Returns the list of Ids that has been removed
///
///
public List RemoveAllAnnotation(string symbol)
{
List removed = new List();
if (_annotations.ContainsKey(symbol))
{
List annotations = _annotations[symbol].ToList();
foreach (CacheableAnnotation annotation in annotations)
{
removed.Add(annotation.Id);
_annotations[symbol].Remove(annotation);
}
}
return removed;
}
///
/// Data structure for storing all annotations.
///
private Dictionary> _annotations = new Dictionary>();
///
/// Caches all current annotations to XML.
///
/// XML string that can be used in Restore.
public string Save()
{
try
{
XmlDocument doc = new XmlDocument();
doc.LoadXml("");
XmlNode annotationsNode = doc.Node("ANNOTATIONS");
foreach (string symbol in _annotations.Keys)
{
XmlNode symbolNode = annotationsNode.NewNode("SYMBOL");
symbolNode.SetProperty("SYMBOL", symbol);
foreach (CacheableAnnotation annotation in _annotations[symbol])
{
annotation.Save(symbolNode);
}
}
return doc.OuterXml;
}
catch (Exception e)
{
string debugView = e.StackTrace;
return "";
}
}
///
/// Restores annotations from XML.
///
///
public void Restore(string xml)
{
try
{
_annotations.Clear();
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlNode annotationsNode = doc.Node(0);
foreach (XmlNode symbolNode in annotationsNode.ChildNodes)
{
string symbol = symbolNode.Property("SYMBOL", "");
List annotations = new List();
foreach (XmlNode annotationNode in symbolNode.ChildNodes)
{
CacheableAnnotation annotation = new CacheableAnnotation();
annotation.Restore(annotationNode);
annotations.Add(annotation);
}
_annotations.Add(symbol, annotations);
}
}
catch { }
}
}
///
/// Generic object to cache a single annotation. Some properties will be used for some annotation types while others will be used for all annotation types.
///
public class CacheableAnnotation
{
public CacheableAnnotation() { }
public ChartTimeframe ChartTimeframe { get; set; }
public AnnotationType AnnotationType { get; set; }
public double Height { get; set; }
public double Width { get; set; }
public double Y { get; set; }
public Color Color { get; set; }
public double StartTime { get; set; }
public string Id { get; set; }
public string Text { get; set; }
public int LineWidth { get; set; }
public override bool Equals(object obj)
{
CacheableAnnotation cacheableAnnotation = obj as CacheableAnnotation;
if (null == cacheableAnnotation)
return false;
return cacheableAnnotation.Id == Id;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public void Save(XmlNode parent)
{
XmlNode newNode = parent.NewNode("ANNOTATION");
newNode.SetProperty("TIMEFRAME", ChartTimeframe);
newNode.SetProperty("TYPE", AnnotationType);
newNode.SetProperty("HEIGHT", Height);
newNode.SetProperty("WIDTH", Width);
newNode.SetProperty("Y", Y);
newNode.SetProperty("COLOR", Color);
newNode.SetProperty("START_TIME", StartTime);
newNode.SetProperty("ID", Id);
newNode.SetProperty("TEXT", Text);
newNode.SetProperty("LineWidth", LineWidth);
}
public void Restore(XmlNode description)
{
ChartTimeframe = description.PropertyEnum("TIMEFRAME", ChartTimeframe.Daily);
AnnotationType = description.PropertyEnum("TYPE", TIProGUI.AnnotationType.Trendline);
Height = description.Property("HEIGHT", 0.0);
Width = description.Property("WIDTH", 0.0);
Y = description.Property("Y", 0.0);
Color = description.Property("COLOR", Color.Black);
StartTime = description.Property("START_TIME", 0.0);
Id = description.Property("ID", "");
Text = description.Property("TEXT", "");
LineWidth = description.Property("LineWidth", 2);
}
}
public enum AnnotationType { HorizontalLine, Arrow, Trendline, Text };
}