1059 lines
25 KiB
C#

using System;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using DevComponents.DotNetBar.Charts.Style;
namespace DevComponents.DotNetBar.Charts
{
#region XmlSerializableFont
static public class XmlSerializableFont
{
static public string ConvertToString(Font font)
{
if (font != null)
{
TypeConverter converter =
TypeDescriptor.GetConverter(typeof(Font));
return (converter.ConvertToString(font));
}
return (null);
}
static public Font ConvertFromString(string fontString)
{
TypeConverter converter =
TypeDescriptor.GetConverter(typeof(Font));
Font font = (Font)converter.ConvertFromString(fontString);
return (font);
}
}
#endregion
#region XmlSerializableImageList
static public class XmlSerializableImageList
{
static public string ConvertToString(ImageList list)
{
TypeConverter converter =
TypeDescriptor.GetConverter(typeof(ImageList));
return (converter.ConvertToString(list));
}
static public ImageList ConvertFromString(string listString)
{
TypeConverter converter =
TypeDescriptor.GetConverter(typeof(ImageList));
ImageList list = (ImageList)converter.ConvertFromString(listString);
return (list);
}
}
#endregion
#region SerialElementCollection
public delegate void Pv(SerialElement se);
public delegate void Pc(SerialElement se);
public class SerialElementCollection : CustomCollection<SerialElement>
{
#region Private variables
private int _ReadIndex = -1;
private SerialElement _ReadSe;
private string _Name;
private int _ValueIndex;
#endregion
#region Internal properties
#region Eof
internal bool Eof
{
get { return (_ReadIndex >= Count); }
}
#endregion
#region Name
internal string Name
{
get { return (_Name); }
set { _Name = value; }
}
#endregion
#region ReadIndex
internal int ReadIndex
{
get { return (_ReadIndex); }
set { _ReadIndex = value; }
}
#endregion
#region ReadSe
internal SerialElement ReadSe
{
get { return (_ReadSe); }
}
#endregion
#endregion
#region AddStartElement
/// <summary>
/// Adds a 'Start' element to the collection.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public SerialElement AddStartElement(string name)
{
SerialElement se = new SerialElement(SerElementType.Start, name);
Items.Add(se);
return (se);
}
#endregion
#region AddEndElement
/// <summary>
/// Adds an 'End' element to the collection.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public SerialElement AddEndElement(string name)
{
SerialElement se = new SerialElement(SerElementType.End, name);
Items.Add(se);
return (se);
}
#endregion
#region AddValue
/// <summary>
/// Adds the given object element to the collection.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public SerialElement AddValue(object value)
{
SerialElement se = new SerialElement(null, value);
Items.Add(se);
return (se);
}
/// <summary>
/// Adds the given value to the collection (surrounded
/// by a 'Start' and 'End' element pair).
/// </summary>
/// <param name="name"></param>
/// <param name="value"></param>
public void AddValue(string name, object value)
{
Items.Add(new SerialElement(SerElementType.ValueStart, name));
Items.Add(new SerialElement(name, value));
Items.Add(new SerialElement(SerElementType.ValueEnd, name));
}
/// <summary>
/// Adds the given value to the collection (surrounded
/// by a 'Start' and 'End' element pair) - but only if the
/// value is not equal to the given defaultValue.
/// </summary>
/// <param name="name"></param>
/// <param name="value"></param>
/// <param name="defaultValue"></param>
public void AddValue(string name, object value, object defaultValue)
{
if ((defaultValue == null && value != null) ||
(defaultValue != null && defaultValue.Equals(value) == false))
{
AddValue(name, value);
}
}
/// <summary>
/// Adds the given value Image to the collection (surrounded
/// by a 'Start' and 'End' element pair).
/// </summary>
/// <param name="name"></param>
/// <param name="image"></param>
public void AddValue(string name, Image image)
{
if (image != null)
AddValue(name, ImageToString(image));
}
#endregion
#region ImageToString
private String ImageToString(Image image)
{
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, image);
return (Convert.ToBase64String(ms.ToArray()));
}
#endregion
#region AddDataValue
/// <summary>
/// Adds the given 'Data' value to the collection (surrounded
/// by a 'Start' and 'End' element pair).
/// </summary>
/// <param name="name"></param>
/// <param name="value"></param>
public void AddDataValue(string name, object value)
{
Items.Add(new SerialElement(SerElementType.ValueStart, name));
Items.Add(new SerialElement(SerElementType.DataValue, name, value));
Items.Add(new SerialElement(SerElementType.ValueEnd, name));
}
/// <summary>
/// Adds the given 'Data' value to the collection (surrounded
/// by a 'Start' and 'End' element pair) - but only if the
/// value is not equal to the given defaultValue.
/// </summary>
/// <param name="name"></param>
/// <param name="value"></param>
/// <param name="defaultValue"></param>
public void AddDataValue(string name, object value, object defaultValue)
{
if ((defaultValue == null && value != null) ||
(defaultValue != null && defaultValue.Equals(value) == false))
{
AddDataValue(name, value);
}
}
#endregion
#region AddElement
/// <summary>
/// Adds the given SerialElementCollection to the
/// collection, if the given collection is non-empty.
/// </summary>
/// <param name="sec"></param>
/// <returns></returns>
public SerialElement AddElement(SerialElementCollection sec)
{
if (sec != null && sec.Count > 0)
{
int count = sec.Count;
if (sec[count - 1].SerType == SerElementType.End)
count--;
if (sec[0].SerType == SerElementType.Start)
count--;
if (count > 0)
{
SerialElement se = new SerialElement(sec);
Items.Add(se);
return (se);
}
}
return (null);
}
/// <summary>
/// Adds the given style to the collection, if
/// it is not Empty.
/// </summary>
/// <param name="style"></param>
/// <returns></returns>
public SerialElement AddElement(BaseVisualStyle style)
{
if (style != null && style.IsEmpty == false)
return (AddElement(style.GetSerialData("")));
return (null);
}
#endregion
#region PutSerialData
internal void PutSerialData(IProcessSerialElement ipse)
{
while (Read())
{
SerialElement se = ReadSe;
switch (se.SerType)
{
case SerElementType.Start:
case SerElementType.ValueStart:
string name = se.Name;
PutSerialData(ipse);
if (se.Name.Equals(name) == false)
throw new Exception("Expecting " + name + " End");
break;
case SerElementType.Value:
se.ValueIndex = _ValueIndex++;
ipse.ProcessValue(se);
break;
case SerElementType.Collection:
int valueIndex = _ValueIndex;
_ValueIndex = 0;
ipse.ProcessCollection(se);
_ValueIndex = valueIndex;
break;
case SerElementType.End:
case SerElementType.ValueEnd:
return;
}
}
}
#region SkipSerialData
private void SkipSerialData()
{
while (Read())
{
SerialElement se = ReadSe;
switch (se.SerType)
{
case SerElementType.Start:
case SerElementType.ValueStart:
string name = se.Name;
SkipSerialData();
if (se.Name.Equals(name) == false)
throw new Exception("Expecting " + name + " End");
break;
case SerElementType.End:
case SerElementType.ValueEnd:
return;
}
}
}
#endregion
#endregion
#region Read
internal bool Read()
{
_ReadIndex++;
_ReadSe = (_ReadIndex < Count) ? Items[_ReadIndex] : null;
return (_ReadSe != null);
}
#endregion
#region Rewind
internal void Rewind()
{
_ReadIndex = -1;
}
#endregion
#region GetItemValue
internal string GetItemValue(string text)
{
foreach (SerialElement se in this)
{
if (se.SerType == SerElementType.Value)
{
if (se.Name.Equals(text))
return (se.StringValue);
}
}
return (null);
}
#endregion
}
#endregion
#region SerialElement
public class SerialElement
{
#region Private variables
private SerElementType _SerType;
private string _Name;
private object _Value;
private SerialElementCollection _Sec;
private int _ArrayCount;
private int _ValueIndex;
#endregion
#region Constructors
public SerialElement(SerElementType type, string name)
{
_SerType = type;
_Name = name;
}
public SerialElement(string name, object value)
{
_SerType = SerElementType.Value;
_Name = name;
_Value = value;
}
public SerialElement(SerElementType type, string name, object value)
{
_SerType = type;
_Name = name;
_Value = value;
}
public SerialElement(SerialElementCollection sec)
{
_SerType = SerElementType.Collection;
_Sec = sec;
}
#endregion
#region Public properties
/// <summary>
/// Element name
/// </summary>
public string Name
{
get { return (_Name); }
set { _Name = value; }
}
/// <summary>
/// Element type.
/// </summary>
public SerElementType SerType
{
get { return (_SerType); }
set { _SerType = value; }
}
/// <summary>
/// Element value
/// </summary>
public object Value
{
get { return (_Value); }
set { _Value = value; }
}
/// <summary>
/// Element sub-collection.
/// </summary>
public SerialElementCollection Sec
{
get { return (_Sec); }
set { _Sec = value; }
}
#endregion
#region Internal properties
#region ArrayCount
internal int ArrayCount
{
get { return (_ArrayCount); }
set { _ArrayCount = value; }
}
#endregion
#region ColorValue
internal Color ColorValue
{
get { return (GetValueColor()); }
}
#endregion
#region DataValue
internal object DataValue
{
get
{
if (Value is string)
{
string s = (string)Value;
if (s.StartsWith("\"") && s.EndsWith("\""))
return (s.Substring(1, s.Length - 2));
if (s.StartsWith("#") && s.EndsWith("#"))
return (DateTime.Parse(s.Substring(1, s.Length - 2)));
if (s.StartsWith("{") && s.EndsWith("}"))
return (ColorTranslator.FromHtml(s.Substring(1, s.Length - 2)));
if (s.StartsWith("[") && s.EndsWith("]"))
{
s = s.Substring(1, s.Length - 2);
string[] t = s.Split(',');
TypeCode tc = TypeCode.Double;
if (t.Length > 1)
tc = (TypeCode)int.Parse(t[1]);
return (GetNumericValue(t[0], tc));
}
if (s.Equals("xsi:nil=\"true\""))
return (null);
return (s);
}
return (null);
}
}
#endregion
#region StringValue
internal string StringValue
{
get
{
if (Value is string)
{
string s = (string)Value;
if (s.StartsWith("\"") && s.EndsWith("\""))
return (s.Substring(1, s.Length - 2));
return (s);
}
return ("");
}
}
#endregion
#region ValueIndex
internal int ValueIndex
{
get { return (_ValueIndex); }
set { _ValueIndex = value; }
}
#endregion
#endregion
#region GetValueColor
internal Color GetValueColor()
{
string s = StringValue;
if (string.IsNullOrEmpty(s) == false)
{
if (s.IndexOf('=') >= 0)
{
string pattern = @"A=(?<A>\d+)\s*,\s*R=(?<R>\d+)\s*,\s*G=(?<G>\d+)\s*,\s*B=(?<B>\d+)";
Match match = Regex.Match(s, pattern);
if (match.Success == true)
{
Color color = Color.FromArgb(
int.Parse(match.Groups["A"].Value),
int.Parse(match.Groups["R"].Value),
int.Parse(match.Groups["G"].Value),
int.Parse(match.Groups["B"].Value));
return (color);
}
}
else
{
return (Color)Color.FromName(s);
}
}
return (Color.Empty);
}
#endregion
#region GetValueString
internal string GetValueString()
{
string s = GetValueStringEx();
string encodedXml = SecurityElement.Escape(s);
return (encodedXml);
}
internal string GetValueStringEx()
{
object value = Value;
if (value == null)
return ("xsi:nil=\"true\"");
if (value is string)
return ((string)value);
if (value is DateTime)
return (((DateTime)value).ToString("o"));
if (value is Color)
{
Color color = (Color)value;
string s = color.ToString();
int start = s.IndexOf('[') + 1;
int end = s.IndexOf(']');
s = s.Substring(start, end - start);
return (s);
}
return (value.ToString());
}
#endregion
#region GetDataValueString
internal string GetDataValueString()
{
object value = Value;
if (value == null)
return ("xsi:nil=\"true\"");
if (value is string)
return ("\"" + value + "\"");
if (value is DateTime)
return ("#" + ((DateTime)value).ToString("o") + "#");
if (value is Color)
return ("{" + ColorTranslator.ToHtml((Color)value) + "}");
if (Value is Enum == false)
{
TypeCode typeCode;
if (IsNumericValue(out typeCode))
{
string s = value.ToString();
return ("[" + s + "," + (int)typeCode + "]");
}
}
return (value.ToString());
}
#endregion
#region GetValueEnum
internal object GetValueEnum(Type type)
{
return (Enum.Parse(type, StringValue));
}
#endregion
#region GetValuePoint
internal Point GetValuePoint()
{
string svalue = StringValue;
if (string.IsNullOrEmpty(svalue) == false)
{
string pattern = @"(?<x>X=\d+)\s,\s(?<y>Y=\d+)";
Match match = Regex.Match(svalue, pattern);
if (match.Success == true)
{
Point pt = new Point(
int.Parse(match.Groups["x"].Value),
int.Parse(match.Groups["y"].Value));
return (pt);
}
}
return (Point.Empty);
}
#endregion
#region GetValuePointF
internal PointF GetValuePointF()
{
string svalue = StringValue;
if (string.IsNullOrEmpty(svalue) == false)
{
string pattern = @"(?<x>X=\d+)\s,\s(?<y>Y=\d+)";
Match match = Regex.Match(svalue, pattern);
if (match.Success == true)
{
PointF ptf = new PointF(
float.Parse(match.Groups["x"].Value),
float.Parse(match.Groups["y"].Value));
return (ptf);
}
}
return (PointF.Empty);
}
#endregion
#region GetValueSize
internal Size GetValueSize()
{
string svalue = StringValue;
if (string.IsNullOrEmpty(svalue) == false)
{
string pattern = @"Width=(?<width>\d+)\s*,\s*Height=(?<height>\d+)";
Match match = Regex.Match(svalue, pattern);
if (match.Success == true)
{
Size size = new Size(
int.Parse(match.Groups["width"].Value),
int.Parse(match.Groups["height"].Value));
return (size);
}
}
return (Size.Empty);
}
#endregion
#region GetValueRect
internal Rectangle GetValueRect()
{
string svalue = StringValue;
if (string.IsNullOrEmpty(svalue) == false)
{
string pattern = @"(?<x>X=\d+)\s,\s(?<x>Y=\d+)\s,\s(?<width>Width=\d+)\s,\s(?<height>Height=\d+)";
Match match = Regex.Match(svalue, pattern);
if (match.Success == true)
{
Rectangle rect = new Rectangle(
int.Parse(match.Groups["x"].Value),
int.Parse(match.Groups["y"].Value),
int.Parse(match.Groups["width"].Value),
int.Parse(match.Groups["height"].Value));
return (rect);
}
}
return (Rectangle.Empty);
}
#endregion
#region GetValueImage
internal Image GetValueImage()
{
string svalue = StringValue;
if (string.IsNullOrEmpty(svalue) == false)
return (StringToImage(svalue));
return (null);
}
#region StringToImage
private Image StringToImage(String data)
{
MemoryStream ms = new MemoryStream(Convert.FromBase64String(data));
BinaryFormatter bf = new BinaryFormatter();
Image image = (Image)bf.Deserialize(ms);
return (image);
}
#endregion
#endregion
#region IsNumericValue
private bool IsNumericValue(out TypeCode typeCode)
{
typeCode = Type.GetTypeCode(Value.GetType());
switch (typeCode)
{
case TypeCode.Byte:
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.SByte:
case TypeCode.Single:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
return (true);
}
return (false);
}
#endregion
#region GetNumericValue
private object GetNumericValue(string s, TypeCode typeCode)
{
switch (typeCode)
{
case TypeCode.Byte:
return (Byte.Parse(s));
case TypeCode.Decimal:
return (Decimal.Parse(s));
case TypeCode.Double:
return (Double.Parse(s));
case TypeCode.Int16:
return (Int16.Parse(s));
case TypeCode.Int32:
return (Int32.Parse(s));
case TypeCode.Int64:
return (Int64.Parse(s));
case TypeCode.SByte:
return (SByte.Parse(s));
case TypeCode.Single:
return (Single.Parse(s));
case TypeCode.UInt16:
return (UInt16.Parse(s));
case TypeCode.UInt32:
return (UInt32.Parse(s));
case TypeCode.UInt64:
return (UInt64.Parse(s));
}
return (false);
}
#endregion
}
#endregion
#region Interfaces
internal interface IProcessSerialElement
{
void ProcessValue(SerialElement se);
void ProcessCollection(SerialElement se);
}
#endregion
#region SerElementType enum
public enum SerElementType
{
Start,
End,
ValueStart,
ValueEnd,
Value,
DataValue,
Collection,
}
#endregion
#region StreamWriterNC
public class StreamWriterNC : IDisposable
{
#region Private variables
private Stream _Stream;
#endregion
public StreamWriterNC(Stream stream)
{
_Stream = stream;
stream.Position = 0;
}
#region Public properties
public Stream Stream
{
get { return (_Stream); }
internal set { _Stream = value; }
}
#endregion
#region Write
public void Write(string s)
{
byte[] bytes = new byte[s.Length * sizeof(char)];
Buffer.BlockCopy(s.ToCharArray(), 0, bytes, 0, bytes.Length);
_Stream.Write(bytes, 0, bytes.Length);
}
#endregion
#region WriteLine
public void WriteLine(string s)
{
Write(s + "\n");
}
public void WriteLine()
{
Write("\n");
}
#endregion
#region Dispose
public void Dispose()
{
_Stream.Flush();
}
#endregion
}
#endregion
}