1770 lines
45 KiB
C#

using System;
using System.ComponentModel;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using System.Xml;
using DevComponents.DotNetBar.Charts.Style;
namespace DevComponents.DotNetBar.Charts
{
[DesignTimeVisible(false)]
public abstract class ChartElement : INotifyPropertyChanged, INamed, IDisposable
{
#region Events
/// <summary>
/// Occurs when parent of the item has changed.
/// </summary>
public event EventHandler ParentChanged;
/// <summary>
/// Occurs when display/rendering of the item is invalidated.
/// </summary>
public event EventHandler RenderInvalid;
/// <summary>
/// Occurs when layout of the item is invalidated.
/// </summary>
public event EventHandler LayoutInvalid;
#endregion
#region Private variables
private string _Name = String.Empty;
private ChartControl _ChartControl;
private ChartElement _Parent;
private object _Tag;
#endregion
#region Public properties
#region ChartControl
/// <summary>
/// Gets the parent ChartControl
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public ChartControl ChartControl
{
get { return (GetChartControl()); }
internal set { _ChartControl = value; }
}
#region GetChartControl
private ChartControl GetChartControl()
{
if (_ChartControl != null)
return (_ChartControl);
ChartElement parent = _Parent;
while (parent != null)
{
if (parent.ChartControl != null)
return (parent.ChartControl);
parent = parent.Parent;
}
return (null);
}
#endregion
#endregion
#region ChartPanel
/// <summary>
/// Gets the parent ChartPanel
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public ChartPanel ChartPanel
{
get { return (GetChartPanel()); }
}
#region GetChartPanel
private ChartPanel GetChartPanel()
{
ChartElement item = this;
while (item != null)
{
if (item is ChartPanel)
return ((ChartPanel)item);
item = item.Parent;
}
return (null);
}
#endregion
#endregion
#region Name
/// <summary>
/// Gets or sets the Name of the item.
/// </summary>
[DefaultValue("")]
[Description("Indicates the Name of the item.")]
public virtual string Name
{
get { return (_Name); }
set { _Name = value; }
}
#endregion
#region Parent
/// <summary>
/// Gets or sets the parent of the item.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public virtual ChartElement Parent
{
get { return (_Parent); }
internal set
{
if (_Parent != value)
{
ChartElement oldParent = _Parent;
_Parent = value;
OnParentChanged(oldParent, value);
}
}
}
#region OnParentChanged
/// <summary>
/// Called after parent of the item has changed.
/// </summary>
/// <param name="oldParent">Reference to old parent.</param>
/// <param name="newParent">Reference to new parent.</param>
protected virtual void OnParentChanged(ChartElement oldParent, ChartElement newParent)
{
if (oldParent != null)
oldParent.ParentChanged -= GrapdParentChanged;
if (newParent != null)
newParent.ParentChanged += GrapdParentChanged;
OnParentChanged(EventArgs.Empty);
}
void GrapdParentChanged(object sender, EventArgs e)
{
ChartElement parent = sender as ChartElement;
if (parent != null)
Parent = parent;
}
/// <summary>
/// Raises ParentChanged event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnParentChanged(EventArgs e)
{
EventHandler handler = ParentChanged;
if (handler != null)
handler(this, e);
}
#endregion
#endregion
#region ParentChartContainer
/// <summary>
/// Gets the parent ChartContainer
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public ChartContainer ParentChartContainer
{
get { return (GetParentChartContainer()); }
}
#region GetParentChartContainer
private ChartContainer GetParentChartContainer()
{
ChartElement parent = _Parent;
while (parent != null)
{
if (parent is ChartContainer)
return ((ChartContainer)parent);
parent = parent.Parent;
}
return (null);
}
#endregion
#endregion
#region Tag
///<summary>
/// Gets or sets user-defined data associated with the object
///</summary>
[DefaultValue(null)]
[Description("User-defined data associated with the object")]
[TypeConverter(typeof(StringConverter))]
public object Tag
{
get { return (_Tag); }
set { _Tag = value; }
}
#endregion
#endregion
#region OnLayoutInvalid
/// <summary>
/// Raises LayoutInvalid event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnLayoutInvalid(EventArgs e)
{
EventHandler handler = LayoutInvalid;
if (handler != null)
handler(this, e);
}
#endregion
#region OnRenderInvalid
/// <summary>
/// Raises RenderInvalid event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnRenderInvalid(EventArgs e)
{
EventHandler handler = RenderInvalid;
if (handler != null)
handler(this, e);
}
#endregion
#region INotifyPropertyChanged Members
/// <summary>
/// Occurs when property value has changed.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises the PropertyChanged event.
/// </summary>
/// <param name="e">Event arguments</param>
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChangedEventHandler eh = PropertyChanged;
if (eh != null)
eh(this, e);
}
/// <summary>
/// Default PropertyChanged processing
/// </summary>
/// <param name="s"></param>
protected void OnPropertyChanged(string s)
{
if (PropertyChanged != null)
OnPropertyChanged(new PropertyChangedEventArgs(s));
}
#endregion
#region IDisposable
public virtual void Dispose()
{
Parent = null;
}
#endregion
}
[ToolboxItem(false)]
public abstract class ChartVisualElement : ChartElement, IEffectiveStyle, IProcessSerialElement
{
#region Static variables
static Point _mouseDownPoint;
static Cursor _OpenHandCursor;
static Cursor _ClosedHandCursor;
#endregion
#region Private variables
private Es _States;
private Rectangle _BoundsRelative;
private Point _ScrollOffset;
private ChartVisualElement _HitItem;
#endregion
#region Constructor
/// <summary>
/// ChartVisualElement
/// </summary>
protected ChartVisualElement()
{
SetState(Es.Visible, true);
}
#endregion
#region Abstract methods
/// <summary>
/// Performs the layout of the item
/// and sets the Size property to size that item will take.
/// </summary>
/// <param name="layoutInfo">Layout information.</param>
protected abstract void MeasureOverride(ChartLayoutInfo layoutInfo);
/// <summary>
/// Performs the arrange pass layout of the item when
/// the final position and size of the item has been set.
/// </summary>
/// <param name="layoutInfo">Layout information.</param>
protected abstract void ArrangeOverride(ChartLayoutInfo layoutInfo);
/// <summary>
/// Performs drawing of the item and its children.
/// </summary>
/// <param name="renderInfo">Holds contextual rendering information.</param>
protected abstract void RenderOverride(ChartRenderInfo renderInfo);
#endregion
#region Public properties
#region Bounds
/// <summary>
/// Gets or sets the absolute (scroll adjusted) bounds of the item.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public virtual Rectangle Bounds
{
get { return (GetScrollBounds(_BoundsRelative)); }
}
#endregion
#region BoundsRelative
/// <summary>
/// Gets or sets the relative bounds of the item.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public virtual Rectangle BoundsRelative
{
get { return (_BoundsRelative); }
internal set { _BoundsRelative = value; }
}
#endregion
#region IsMouseOver
/// <summary>
/// Gets whether mouse is over the element.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public virtual bool IsMouseOver
{
get { return (TestState(Es.MouseOver)); }
internal set { SetState(Es.MouseOver, value); }
}
#endregion
#region Size
/// <summary>
/// Gets or sets the Size of the item.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Size Size
{
get { return (_BoundsRelative.Size); }
internal set { _BoundsRelative.Size = value; }
}
#endregion
#region Visible
/// <summary>
/// Get or sets whether the item is visible
/// </summary>
[DefaultValue(true), Category("Appearance")]
[Description("Indicates whether the item is visible")]
public virtual bool Visible
{
get { return (TestState(Es.Visible)); }
set
{
if (Visible != value)
{
SetState(Es.Visible, value);
OnPropertyChangedEx("Visible", VisualChangeType.Layout);
}
}
}
#endregion
#endregion
#region Internal properties
#region Capture
internal virtual bool Capture
{
get { return (CapturedItem != null); }
set
{
if (ChartControl != null)
CapturedItem = (value == true) ? this : null;
}
}
#endregion
#region CapturedItem
internal ChartVisualElement CapturedItem
{
get
{
if (ChartControl != null)
return (ChartControl.CapturedItem);
return (null);
}
set
{
if (ChartControl != null)
ChartControl.CapturedItem = value;
}
}
#endregion
#region ChartCursor
internal Cursor ChartCursor
{
get
{
ChartControl cc = ChartControl;
if (cc != null)
return (cc.ChartCursor);
return (Cursors.Default);
}
set
{
ChartControl cc = ChartControl;
if (cc != null)
cc.ChartCursor = value;
}
}
#endregion
#region ClosedHandCursor
internal Cursor ClosedHandCursor
{
get
{
if (_ClosedHandCursor == null)
_ClosedHandCursor = new Cursor(GetType(), "ClosedHand.cur");
return (_ClosedHandCursor);
}
}
#endregion
#region HitItem
internal ChartVisualElement HitItem
{
get { return (_HitItem); }
set { _HitItem = value; }
}
#endregion
#region Displayed
/// <summary>
/// Gets whether element is actually displayed on screen
/// </summary>
internal bool Displayed
{
get { return (TestState(Es.Displayed)); }
set { SetState(Es.Displayed, value); }
}
#endregion
#region IsMouseDown
/// <summary>
/// Gets whether mouse is down
/// </summary>
internal virtual bool IsMouseDown
{
get { return (Control.MouseButtons != MouseButtons.None); }
}
#endregion
#region MouseDownPoint
/// <summary>
/// Gets the mouse down Point
/// </summary>
internal virtual Point MouseDownPoint
{
get { return (_mouseDownPoint); }
set { _mouseDownPoint = value; }
}
#endregion
#region MouseOverElement
internal ChartVisualElement MouseOverElement
{
get { return (ChartControl.MouseOverElement); }
set { ChartControl.MouseOverElement = value; }
}
#endregion
#region OpenHandCursor
internal Cursor OpenHandCursor
{
get
{
if (_OpenHandCursor == null)
_OpenHandCursor = new Cursor(GetType(), "OpenHand.cur");
return (_OpenHandCursor);
}
}
#endregion
#region ScrollOffset
internal Point ScrollOffset
{
get { return (_ScrollOffset); }
set { _ScrollOffset = value; }
}
#endregion
#endregion
#region Measure
/// <summary>
/// This method is used by the items internally to invoke the measure pass to
/// get item size. Override MeasureOverride method to perform actual measuring.
/// </summary>
/// <param name="layoutInfo">Holds contextual layout information.</param>
internal void Measure(ChartLayoutInfo layoutInfo)
{
MeasureOverride(layoutInfo);
}
#endregion
#region Arrange
/// <summary>
/// This method is used by the items internally to invoke the arrange pass after
/// location and size of the item has been set. Override ArrangeOverride method
/// to perform internal arranging.
/// </summary>
/// <param name="layoutInfo"></param>
/// <param name="layoutBounds"></param>
internal void Arrange(ChartLayoutInfo layoutInfo)
{
Displayed = true;
_ScrollOffset = layoutInfo.ScrollOffset;
ArrangeOverride(layoutInfo);
}
#endregion
#region Render
private int _RenderCount;
/// <summary>
/// This method is used by the items internally to invoke the rendering
/// for the item. Override RenderOverride method to perform actual rendering.
/// </summary>
/// <param name="renderInfo">Holds contextual rendering information.</param>
internal virtual void Render(ChartRenderInfo renderInfo)
{
if (Displayed == true && renderInfo.ClipRectangle.IntersectsWith(Bounds))
{
RenderOverride(renderInfo);
//Graphics g = renderInfo.Graphics;
//using (StringFormat sf = new StringFormat())
//{
// sf.LineAlignment = StringAlignment.Center;
// sf.Alignment = StringAlignment.Center;
// _RenderCount++;
// g.DrawString(_RenderCount.ToString(), SystemFonts.CaptionFont, Brushes.Red, Bounds, sf);
//}
}
}
#endregion
#region CancelCapture
///<summary>
/// Cancels any inprogress operations that may
/// have the mouse captured (resize, reorder).
///</summary>
public virtual void CancelCapture()
{
if (CapturedItem == this)
Capture = false;
}
#endregion
#region InvalidateRecalc
internal virtual void InvalidateRecalc()
{
InvalidateLayout();
}
#endregion
#region InvalidateLayout
/// <summary>
/// Invalidates the layout for the item.
/// </summary>
public virtual void InvalidateLayout()
{
ChartControl control = ChartControl;
if (control != null)
{
control.LayoutValid = false;
if (control.InUpdateLayout == true)
control.PostInternalUpdate = true;
else
control.Invalidate();
}
OnLayoutInvalid(EventArgs.Empty);
}
#endregion
#region InvalidateRender
/// <summary>
/// Invalidates the display state of the item
/// </summary>
public virtual void InvalidateRender()
{
ChartControl chartControl = ChartControl;
if (chartControl != null)
{
if (chartControl.InvokeRequired)
chartControl.BeginInvoke(new MethodInvoker(delegate { chartControl.InvalidateRender(this); }));
else
chartControl.InvalidateRender(this);
}
OnRenderInvalid(EventArgs.Empty);
}
/// <summary>
/// Invalidates the display state of the item
/// </summary>
public virtual void InvalidateRender(Rectangle bounds)
{
ChartControl chartControl = ChartControl;
if (chartControl != null)
chartControl.InvalidateRender(bounds);
OnRenderInvalid(EventArgs.Empty);
}
#endregion
#region InvalidateLayoutBounds
/// <summary>
/// Invalidates the layout bounds
/// </summary>
public virtual void InvalidateLayoutBounds(ScrollBarLite sbar)
{
ChartControl.LayoutBoundsItem = this;
}
#endregion
#region GetElementAt
/// <summary>
/// Gets the visual chart element at the given Point.
/// </summary>
/// <param name="pt"></param>
/// <returns></returns>
public virtual ChartVisualElement GetElementAt(Point pt)
{
return (null);
}
#endregion
#region GetHitArea
/// <summary>
/// Gets the element Hit Area for the given Point.
/// </summary>
/// <param name="pt"></param>
/// <returns></returns>
public virtual ItemHitArea GetHitArea(Point pt)
{
return (ItemHitArea.None);
}
#endregion
#region Mouse Handling
#region OnMouseEnter
/// <summary>
/// Called by top-level control to pass message into the grid
/// element. To handle it override corresponding On - virtual method.
/// </summary>
/// <param name="e"></param>
internal virtual bool InternalMouseEnter(EventArgs e)
{
IsMouseOver = true;
return (OnMouseEnter(e));
}
/// <summary>
/// Called when the mouse enters the element.
/// </summary>
/// <param name="e"></param>
protected virtual bool OnMouseEnter(EventArgs e)
{
return (true);
}
#endregion
#region OnMouseLeave
/// <summary>
/// Called by top-level control to pass message into the grid
/// element. To handle it override corresponding On - virtual method.
/// </summary>
/// <param name="e"></param>
internal virtual bool InternalMouseLeave(EventArgs e)
{
IsMouseOver = false;
return (OnMouseLeave(e));
}
/// <summary>
/// Called when mouse leaves the element.
/// </summary>
/// <param name="e"></param>
protected virtual bool OnMouseLeave(EventArgs e)
{
return (true);
}
#endregion
#region OnMouseHover
/// <summary>
/// Called by top-level control to pass message into the grid
/// element. To handle it override corresponding On - virtual method.
/// </summary>
/// <param name="e"></param>
internal virtual bool InternalMouseHover(EventArgs e)
{
return (OnMouseHover(e));
}
/// <summary>
/// Called when mouse hovers over the element.
/// </summary>
/// <param name="e"></param>
protected virtual bool OnMouseHover(EventArgs e)
{
return (false);
}
#endregion
#region OnMouseDown
/// <summary>
/// Called by top-level control to pass message into the grid
/// element. To handle it override corresponding On - virtual method.
/// </summary>
/// <param name="e"></param>
internal virtual bool InternalMouseDown(MouseEventArgs e)
{
MouseDownPoint = e.Location;
bool handled = OnMouseDown(e);
if (handled == false)
{
ChartVisualElement parent = Parent as ChartVisualElement;
while (parent != null)
{
parent.OnMouseMoveEx(e);
if (parent.OnMouseDownEx(e) == true)
return (true);
parent = parent.Parent as ChartVisualElement;
}
}
return (false);
}
/// <summary>
/// Called when mouse button is pressed over the element.
/// </summary>
/// <param name="e"></param>
protected virtual bool OnMouseDown(MouseEventArgs e)
{
return (true);
}
/// <summary>
/// Called when mouse button is pressed over the element.
/// </summary>
/// <param name="e"></param>
protected virtual bool OnMouseDownEx(MouseEventArgs e)
{
return (true);
}
#endregion
#region OnMouseUp
/// <summary>
/// Called by top-level control to pass message into the grid
/// element. To handle it override corresponding On - virtual method.
/// </summary>
/// <param name="e"></param>
internal virtual bool InternalMouseUp(MouseEventArgs e)
{
Capture = false;
return (OnMouseUp(e));
}
/// <summary>
/// Called when mouse button is released over the element.
/// </summary>
/// <param name="e"></param>
protected virtual bool OnMouseUp(MouseEventArgs e)
{
return (true);
}
#endregion
#region OnMouseMove
/// <summary>
/// Called by top-level control to pass message into the chart
/// element. To handle it override corresponding On - virtual method.
/// </summary>
/// <param name="e"></param>
internal virtual bool InternalMouseMove(MouseEventArgs e)
{
ChartVisualElement mouseOverElement = MouseOverElement;
if (this != mouseOverElement)
{
if (mouseOverElement != null)
mouseOverElement.InternalMouseLeave(e);
MouseOverElement = this;
InternalMouseEnter(e);
}
bool handled = OnMouseMove(e);
ChartVisualElement parent = Parent as ChartVisualElement;
while (parent != null)
{
if (handled == false)
handled = parent.OnMouseMove(e);
else
parent.OnMouseMoveEx(e);
parent = parent.Parent as ChartVisualElement;
}
return (false);
}
/// <summary>
/// Called when mouse is moved over the element.
/// </summary>
/// <param name="e"></param>
protected virtual bool OnMouseMove(MouseEventArgs e)
{
return (false);
}
/// <summary>
/// Called when mouse is moved over the element.
/// </summary>
/// <param name="e"></param>
protected virtual void OnMouseMoveEx(MouseEventArgs e)
{
}
#endregion
#region OnMouseClick
/// <summary>
/// Called by top-level control to pass message into the grid
/// element. To handle it override corresponding On - virtual method.
/// </summary>
/// <param name="e"></param>
internal virtual bool InternalMouseClick(MouseEventArgs e)
{
return (OnMouseClick(e));
}
/// <summary>
/// Called when mouse is clicked on the element.
/// </summary>
/// <param name="e"></param>
protected virtual bool OnMouseClick(MouseEventArgs e)
{
return (true);
}
#endregion
#region OnMouseDoubleClick
/// <summary>
/// Called by top-level control to pass message into the grid
/// element. To handle it override corresponding On - virtual method.
/// </summary>
/// <param name="e"></param>
internal virtual bool InternalMouseDoubleClick(MouseEventArgs e)
{
return (OnMouseDoubleClick(e));
}
/// <summary>
/// Called when mouse is double clicked on the element.
/// </summary>
/// <param name="e"></param>
protected virtual bool OnMouseDoubleClick(MouseEventArgs e)
{
return (false);
}
#endregion
#region OnMouseWheel
/// <summary>
/// Called by top-level control to pass message into the grid
/// element. To handle it override corresponding On - virtual method.
/// </summary>
/// <param name="e"></param>
internal virtual bool InternalMouseWheel(MouseEventArgs e)
{
bool handled = OnMouseWheel(e);
if (handled == false)
{
ChartVisualElement parent = Parent as ChartVisualElement;
while (parent != null)
{
if (parent.OnMouseWheel(e) == true)
return (true);
parent = parent.Parent as ChartVisualElement;
}
}
return (false);
}
/// <summary>
/// Called when mousewheel is moved while over the element.
/// </summary>
/// <param name="e"></param>
protected virtual bool OnMouseWheel(MouseEventArgs e)
{
return (false);
}
#endregion
#endregion
#region Keyboard handling
/// <summary>
/// Called by top-level control to pass message into the grid
/// element. To handle it override corresponding On - virtual method.
/// </summary>
/// <param name="keyData"></param>
internal virtual void InternalKeyDown(Keys keyData)
{
OnKeyDown(keyData);
}
/// <summary>
/// Called when mouse button is pressed over the element.
/// </summary>
/// <param name="keyData"></param>
protected virtual void OnKeyDown(Keys keyData)
{
}
#endregion
#region OnResize
internal virtual bool InternalOnResize(EventArgs e)
{
return (OnResize(e));
}
/// <summary>
/// Called when control is resized.
/// </summary>
/// <param name="e"></param>
protected virtual bool OnResize(EventArgs e)
{
return (true);
}
#endregion
#region OnVisualStyleChanged
protected virtual void OnVisualStyleChanged(string property,
INotifyPropertyChanged oldValue, INotifyPropertyChanged newValue)
{
StyleVisualChangeHandler(oldValue, newValue);
OnPropertyChanged(property);
}
#endregion
#region StyleVisualChangeHandler
protected virtual void StyleVisualChangeHandler(
INotifyPropertyChanged oldValue, INotifyPropertyChanged newValue)
{
if (oldValue != null)
oldValue.PropertyChanged -= StyleChanged;
if (newValue != null)
newValue.PropertyChanged += StyleChanged;
}
#region StyleChanged
/// <summary>
/// Occurs when one of element visual styles has property changes.
/// Default implementation invalidates visual appearance of element.
/// </summary>
/// <param name="sender">VisualStyle that changed.</param>
/// <param name="e">Event arguments.</param>
protected virtual void StyleChanged(object sender, PropertyChangedEventArgs e)
{
VisualChangeType changeType = ((VisualPropertyChangedEventArgs)e).ChangeType;
if (changeType == VisualChangeType.Layout)
InvalidateLayout();
else
InvalidateRender();
if (ChartControl != null)
ChartControl.GlobalUpdateCount++;
}
#endregion
#endregion
#region ApplyStyles
public virtual void ApplyStyles(BaseVisualStyle style, StyleType cs)
{
}
public virtual void ApplyStyles(BaseVisualStyle style)
{
}
#endregion
#region ApplyDefaults
public virtual void ApplyDefaults(BaseVisualStyle style, StyleType cs)
{
}
#endregion
#region ClearEffectiveStyles
protected virtual void ClearEffectiveStyles()
{ }
#endregion
#region GetElementStyle
public virtual void GetElementStyle(
IEffectiveStyle chartElement, StyleType styleType, ref BaseVisualStyle style)
{
ChartControl.DoGetElementStyleEvent(this, styleType, ref style);
}
#endregion
#region GetAdjustedBounds
internal Rectangle GetAdjustedBounds(Rectangle bounds, Thickness thickness)
{
if (thickness.IsEmpty == false)
{
if (bounds.Height > Dpi.Height(thickness.Vertical))
{
bounds.Y += Dpi.Height(thickness.Top);
bounds.Height -= Dpi.Height(thickness.Vertical);
}
if (bounds.Width > Dpi.Width(thickness.Horizontal))
{
bounds.X += Dpi.Width(thickness.Left);
bounds.Width -= Dpi.Width(thickness.Horizontal);
}
}
return (bounds);
}
#endregion
#region GetScrollBounds
internal Rectangle GetScrollBounds(Rectangle bounds)
{
bounds.X -= _ScrollOffset.X;
bounds.Y -= _ScrollOffset.Y;
return (bounds);
}
#endregion
#region Export
/// <summary>
/// Exports the chart element to the specified file. The
/// specified file will be created and/or overwritten.
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public void Export(string fileName)
{
string dir = Path.GetDirectoryName(fileName);
if (dir != null)
{
if (Directory.Exists(dir) == false)
Directory.CreateDirectory(dir);
using (FileStream stream = new
FileStream(fileName, FileMode.Create, FileAccess.ReadWrite))
{
Export(stream);
}
}
}
/// <summary>
/// Exports the chart element to the specified stream.
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
public void Export(Stream stream)
{
CultureInfo cinfo = Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
SerialElementCollection sec = new SerialElementCollection();
sec = GetSerialData("");
using (StreamWriterNC sw = new StreamWriterNC(stream))
{
sw.WriteLine("<?xml version=\"1.0\"?>");
ExportData(sw, sec);
}
Thread.CurrentThread.CurrentCulture = cinfo;
}
#region ExportData
private void ExportData(StreamWriterNC sw, SerialElementCollection sec)
{
foreach (SerialElement se in sec)
{
switch (se.SerType)
{
case SerElementType.Start:
sw.WriteLine("<" + se.Name + ">");
break;
case SerElementType.ValueStart:
sw.Write("<" + se.Name + ">");
break;
case SerElementType.Value:
sw.Write(se.GetValueString());
break;
case SerElementType.DataValue:
sw.Write(se.GetDataValueString());
break;
case SerElementType.End:
case SerElementType.ValueEnd:
sw.WriteLine("</" + se.Name + ">");
break;
case SerElementType.Collection:
ExportData(sw, se.Sec);
break;
}
}
}
#endregion
#endregion
#region Import
/// <summary>
/// Imoprts the chart element from the given file path.
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public void Import(string fileName)
{
if (File.Exists(fileName) == true)
{
using (FileStream stream = new
FileStream(fileName, FileMode.Open, FileAccess.Read))
{
Import(stream);
}
}
}
/// <summary>
/// Imoprts the chart element from the given stream.
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
public void Import(Stream stream)
{
CultureInfo cinfo = Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
SerialElementCollection sec;
stream.Position = 0;
using (XmlReader reader = XmlReader.Create(stream))
sec = ImportData(reader, 0);
if (sec.Count > 0)
PutSerialData(sec);
Thread.CurrentThread.CurrentCulture = cinfo;
}
#region ImportData
internal virtual SerialElementCollection ImportData(XmlReader reader, int depth)
{
SerialElementCollection sec = new SerialElementCollection();
string name = "";
bool read = depth > 0;
int arrayCount = 0;
while (read || reader.Read())
{
read = false;
switch (reader.NodeType)
{
case XmlNodeType.Element:
if (reader.Depth == depth)
{
if (reader.IsStartElement())
{
SerialElement se = sec.AddStartElement(reader.Name);
se.ArrayCount = GetArrayCount(reader);
arrayCount = se.ArrayCount;
}
}
else if (reader.Depth > depth)
{
SerialElementCollection sec2 = ImportData(reader, reader.Depth);
SerialElement se = sec.AddElement(sec2);
se.ArrayCount = arrayCount;
se.Name = reader.Name;
sec.Name = reader.Name;
sec.AddEndElement(reader.Name);
}
name = reader.Name;
break;
case XmlNodeType.Text:
sec.AddValue(name, reader.Value);
break;
case XmlNodeType.EndElement:
if (reader.Depth < depth)
return (sec);
sec.AddEndElement(reader.Name);
break;
}
}
return (sec);
}
#region GetArrayCount
private int GetArrayCount(XmlReader reader)
{
if (reader.HasAttributes == true)
{
string count = reader.GetAttribute("count");
if (count != null)
return (int.Parse(count));
}
return (0);
}
#endregion
#endregion
#endregion
#region INotifyPropertyChanged Members
/// <summary>
/// Default PropertyChanged processing
/// </summary>
/// <param name="s"></param>
/// <param name="changeType">invalidate</param>
protected void OnPropertyChangedEx(string s, VisualChangeType changeType)
{
OnPropertyChanged(s);
switch (changeType)
{
case VisualChangeType.Layout:
InvalidateLayout();
break;
case VisualChangeType.Recalc:
InvalidateRecalc();
break;
default:
InvalidateRender();
break;
}
}
protected void OnStyleChanged(string property,
INotifyPropertyChanged oldValue, INotifyPropertyChanged newValue)
{
StyleVisualChangeHandler(oldValue, newValue);
OnPropertyChanged(property);
}
#endregion
#region IsDesignerHosted
internal bool IsDesignerHosted
{
get
{
if (ChartControl != null)
return (ChartControl.DesignerHosted);
return (false);
}
}
#endregion
#region ElementStates
[Flags]
private enum Es
{
LayoutBoundsValid = (1 << 0),
LayoutValid = (1 << 1),
MouseOver = (1 << 2),
Displayed = (1 << 3),
Visible = (1 << 4),
NeedsMeasured = (1 << 5),
}
#region TestState
private bool TestState(Es state)
{
return ((_States & state) == state);
}
#endregion
#region SetState
private void SetState(Es state, bool value)
{
if (value == true)
_States |= state;
else
_States &= ~state;
}
#endregion
#endregion
#region Copy/CopyTo
public virtual ChartVisualElement Copy()
{
return (null);
}
public virtual void CopyTo(ChartVisualElement copy)
{
copy.Name = Name;
copy.Size = Size;
copy.Tag = Tag;
copy.Visible = Visible;
}
#endregion
#region GetSerialData
internal virtual SerialElementCollection GetSerialData(string serialName)
{
if ((String.IsNullOrEmpty(Name) == false) || (Tag != null) || (Visible == false))
{
SerialElementCollection sec = new SerialElementCollection();
if (serialName != null)
{
if (serialName.Equals("") == true)
serialName = "ChartElement";
sec.AddStartElement(serialName);
}
sec.AddValue("Name", Name, String.Empty);
sec.AddValue("Tag", Tag, null);
sec.AddValue("Visible", Visible, true);
if (serialName != null)
sec.AddEndElement(serialName);
return (sec);
}
return (null);
}
#endregion
#region PutSerialData
internal void PutSerialData(SerialElementCollection sec)
{
sec.PutSerialData(this);
}
#region ProcessValue
void IProcessSerialElement.ProcessValue(SerialElement se)
{
ProcessValue(se);
}
internal virtual void ProcessValue(SerialElement se)
{
switch (se.Name)
{
case "Name":
Name = se.StringValue;
break;
case "Tag":
Tag = se.DataValue;
break;
case "Visible":
Visible = bool.Parse(se.StringValue);
break;
default:
throw new Exception("Unknown Serial Value (" + se.Name + ")");
}
}
#endregion
#region ProcessCollection
void IProcessSerialElement.ProcessCollection(SerialElement se)
{
ProcessCollection(se);
}
internal virtual void ProcessCollection(SerialElement se)
{
throw new Exception("Unknown Serial Collection (" + se.Name + ")");
}
#endregion
#endregion
}
#region ItemHitArea
///<summary>
/// Specifies the ItemHitArea hit areas
///</summary>
public enum ItemHitArea
{
///<summary>
/// None
///</summary>
None,
/// <summary>
/// Ancillary AxisX
/// </summary>
InAncillaryAxisX,
/// <summary>
/// Primary AxisX
/// </summary>
InPrimaryAxisX,
/// <summary>
/// Ancillary AxisY
/// </summary>
InAncillaryAxisY,
/// <summary>
/// Primary AxisX
/// </summary>
InPrimaryAxisY,
/// <summary>
/// ScrollBar ArrowIncrease
/// </summary>
ArrowIncrease,
/// <summary>
/// ScrollBar ArrowDecrease
/// </summary>
ArrowDecrease,
/// <summary>
/// ScrollBar TrackIncrease
/// </summary>
TrackIncrease,
/// <summary>
/// ScrollBar ArrowDecrease
/// </summary>
TrackDecrease,
/// <summary>
/// ScrollBar Thumb
/// </summary>
Thumb,
///<summary>
/// Content area
///</summary>
InContent,
///<summary>
/// Frame area
///</summary>
InFrame,
/// <summary>
/// PieSeriesPoint
/// </summary>
InPieSeriesPoint,
/// <summary>
/// Pie Center
/// </summary>
InPieCenter,
/// <summary>
/// Pie Ring Out (Out a ring level)
/// </summary>
InPieRingOut,
/// <summary>
/// In Markup area
/// </summary>
InMarkup,
}
#endregion
}