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
        /// 
        /// Occurs when parent of the item has changed.
        /// 
        public event EventHandler ParentChanged;
        /// 
        /// Occurs when display/rendering of the item is invalidated.
        /// 
        public event EventHandler RenderInvalid;
        /// 
        /// Occurs when layout of the item is invalidated.
        /// 
        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
        /// 
        /// Gets the parent ChartControl
        /// 
        [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
        /// 
        /// Gets the parent ChartPanel
        /// 
        [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
        /// 
        /// Gets or sets the Name of the item.
        /// 
        [DefaultValue("")]
        [Description("Indicates the Name of the item.")]
        public virtual string Name
        {
            get { return (_Name); }
            set { _Name = value; }
        }
        #endregion
        #region Parent
        /// 
        /// Gets or sets the parent of the item.
        /// 
        [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
        /// 
        /// Called after parent of the item has changed.
        /// 
        /// Reference to old parent.
        /// Reference to new parent.
        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;
        }
        /// 
        /// Raises ParentChanged event.
        /// 
        /// Provides event arguments.
        protected virtual void OnParentChanged(EventArgs e)
        {
            EventHandler handler = ParentChanged;
            if (handler != null)
                handler(this, e);
        }
        #endregion
        #endregion
        #region ParentChartContainer
        /// 
        /// Gets the parent ChartContainer
        /// 
        [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
        ///
        /// Gets or sets user-defined data associated with the object
        ///
        [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
        /// 
        /// Raises LayoutInvalid event.
        /// 
        /// Provides event arguments.
        protected virtual void OnLayoutInvalid(EventArgs e)
        {
            EventHandler handler = LayoutInvalid;
            if (handler != null)
                handler(this, e);
        }
        #endregion
        #region OnRenderInvalid
        /// 
        /// Raises RenderInvalid event.
        /// 
        /// Provides event arguments.
        protected virtual void OnRenderInvalid(EventArgs e)
        {
            EventHandler handler = RenderInvalid;
            if (handler != null)
                handler(this, e);
        }
        #endregion
        #region INotifyPropertyChanged Members
        /// 
        /// Occurs when property value has changed.
        /// 
        public event PropertyChangedEventHandler PropertyChanged;
        /// 
        /// Raises the PropertyChanged event.
        /// 
        /// Event arguments
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            PropertyChangedEventHandler eh = PropertyChanged;
            if (eh != null)
                eh(this, e);
        }
        /// 
        /// Default PropertyChanged processing
        /// 
        /// 
        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
        /// 
        /// ChartVisualElement
        /// 
        protected ChartVisualElement()
        {
            SetState(Es.Visible, true);
        }
        #endregion
        #region Abstract methods
        /// 
        /// Performs the layout of the item
        /// and sets the Size property to size that item will take.
        /// 
        /// Layout information.
        protected abstract void MeasureOverride(ChartLayoutInfo layoutInfo);
        /// 
        /// Performs the arrange pass layout of the item when
        /// the final position and size of the item has been set.
        /// 
        /// Layout information.
        protected abstract void ArrangeOverride(ChartLayoutInfo layoutInfo);
        /// 
        /// Performs drawing of the item and its children.
        /// 
        /// Holds contextual rendering information.
        protected abstract void RenderOverride(ChartRenderInfo renderInfo);
        #endregion
        #region Public properties
        #region Bounds
        /// 
        /// Gets or sets the absolute (scroll adjusted) bounds of the item.
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual Rectangle Bounds
        {
            get { return (GetScrollBounds(_BoundsRelative)); }
        }
        #endregion
        #region BoundsRelative
        /// 
        /// Gets or sets the relative bounds of the item.
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual Rectangle BoundsRelative
        {
            get { return (_BoundsRelative); }
            internal set { _BoundsRelative = value; }
        }
        #endregion
        #region IsMouseOver
        /// 
        /// Gets whether mouse is over the element.
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual bool IsMouseOver
        {
            get { return (TestState(Es.MouseOver)); }
            internal set { SetState(Es.MouseOver, value); }
        }
        #endregion
        #region Size
        /// 
        /// Gets or sets the Size of the item.
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Size Size
        {
            get { return (_BoundsRelative.Size); }
            internal set { _BoundsRelative.Size = value; }
        }
        #endregion
        #region Visible
        /// 
        /// Get or sets whether the item is visible
        /// 
        [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
        /// 
        /// Gets whether element is actually displayed on screen
        /// 
        internal bool Displayed
        {
            get { return (TestState(Es.Displayed)); }
            set { SetState(Es.Displayed, value); }
        }
        #endregion
        #region IsMouseDown
        /// 
        /// Gets whether mouse is down
        /// 
        internal virtual bool IsMouseDown
        {
            get { return (Control.MouseButtons != MouseButtons.None); }
        }
        #endregion
        #region MouseDownPoint
        /// 
        /// Gets the mouse down Point
        /// 
        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
        /// 
        /// This method is used by the items internally to invoke the measure pass to
        /// get item size. Override MeasureOverride method to perform actual measuring.
        /// 
        /// Holds contextual layout information.
        internal void Measure(ChartLayoutInfo layoutInfo)
        {
            MeasureOverride(layoutInfo);
        }
        #endregion
        #region Arrange
        /// 
        /// 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.
        /// 
        /// 
        /// 
        internal void Arrange(ChartLayoutInfo layoutInfo)
        {
            Displayed = true;
            _ScrollOffset = layoutInfo.ScrollOffset;
            ArrangeOverride(layoutInfo);
        }
        #endregion
        #region Render
        private int _RenderCount;
        /// 
        /// This method is used by the items internally to invoke the rendering
        /// for the item. Override RenderOverride method to perform actual rendering.
        /// 
        /// Holds contextual rendering information.
        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
        ///
        /// Cancels any inprogress operations that may
        /// have the mouse captured (resize, reorder).
        ///
        public virtual void CancelCapture()
        {
            if (CapturedItem == this)
                Capture = false;
        }
        #endregion
        #region InvalidateRecalc
        internal virtual void InvalidateRecalc()
        {
            InvalidateLayout();
        }
        #endregion
            
        #region InvalidateLayout
        /// 
        /// Invalidates the layout for the item.
        /// 
        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
        /// 
        /// Invalidates the display state of the item
        /// 
        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);
        }
        /// 
        /// Invalidates the display state of the item
        /// 
        public virtual void InvalidateRender(Rectangle bounds)
        {
            ChartControl chartControl = ChartControl;
            if (chartControl != null)
                chartControl.InvalidateRender(bounds);
            OnRenderInvalid(EventArgs.Empty);
        }
        #endregion
        #region InvalidateLayoutBounds
        /// 
        /// Invalidates the layout bounds
        /// 
        public virtual void InvalidateLayoutBounds(ScrollBarLite sbar)
        {
            ChartControl.LayoutBoundsItem = this;
        }
        #endregion
        #region GetElementAt
        /// 
        /// Gets the visual chart element at the given Point.
        /// 
        /// 
        /// 
        public virtual ChartVisualElement GetElementAt(Point pt)
        {
            return (null);
        }
        #endregion
        #region GetHitArea
        /// 
        /// Gets the element Hit Area for the given Point.
        /// 
        /// 
        /// 
        public virtual ItemHitArea GetHitArea(Point pt)
        {
            return (ItemHitArea.None);
        }
        #endregion
        #region Mouse Handling
        #region OnMouseEnter
        /// 
        /// Called by top-level control to pass message into the grid
        /// element. To handle it override corresponding On - virtual method.
        /// 
        /// 
        internal virtual bool InternalMouseEnter(EventArgs e)
        {
            IsMouseOver = true;
            return (OnMouseEnter(e));
        }
        /// 
        /// Called when the mouse enters the element.
        /// 
        /// 
        protected virtual bool OnMouseEnter(EventArgs e)
        {
            return (true);
        }
        #endregion
        #region OnMouseLeave
        /// 
        /// Called by top-level control to pass message into the grid
        /// element. To handle it override corresponding On - virtual method.
        /// 
        /// 
        internal virtual bool InternalMouseLeave(EventArgs e)
        {
            IsMouseOver = false;
            return (OnMouseLeave(e));
        }
        /// 
        /// Called when mouse leaves the element.
        /// 
        /// 
        protected virtual bool OnMouseLeave(EventArgs e)
        {
            return (true);
        }
        #endregion
        #region OnMouseHover
        /// 
        /// Called by top-level control to pass message into the grid
        /// element. To handle it override corresponding On - virtual method.
        /// 
        /// 
        internal virtual bool InternalMouseHover(EventArgs e)
        {
            return (OnMouseHover(e));
        }
        /// 
        /// Called when mouse hovers over the element.
        /// 
        /// 
        protected virtual bool OnMouseHover(EventArgs e)
        {
            return (false);
        }
        #endregion
        #region OnMouseDown
        /// 
        /// Called by top-level control to pass message into the grid
        /// element. To handle it override corresponding On - virtual method.
        /// 
        /// 
        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);
        }
        /// 
        /// Called when mouse button is pressed over the element.
        /// 
        /// 
        protected virtual bool OnMouseDown(MouseEventArgs e)
        {
            return (true);
        }
        /// 
        /// Called when mouse button is pressed over the element.
        /// 
        /// 
        protected virtual bool OnMouseDownEx(MouseEventArgs e)
        {
            return (true);
        }
        #endregion
        #region OnMouseUp
        /// 
        /// Called by top-level control to pass message into the grid
        /// element. To handle it override corresponding On - virtual method.
        /// 
        /// 
        internal virtual bool InternalMouseUp(MouseEventArgs e)
        {
            Capture = false;
            return (OnMouseUp(e));
        }
        /// 
        /// Called when mouse button is released over the element.
        /// 
        /// 
        protected virtual bool OnMouseUp(MouseEventArgs e)
        {
            return (true);
        }
        #endregion
        #region OnMouseMove
        /// 
        /// Called by top-level control to pass message into the chart
        /// element. To handle it override corresponding On - virtual method.
        /// 
        /// 
        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);
        }
        /// 
        /// Called when mouse is moved over the element.
        /// 
        /// 
        protected virtual bool OnMouseMove(MouseEventArgs e)
        {
            return (false);
        }
        /// 
        /// Called when mouse is moved over the element.
        /// 
        /// 
        protected virtual void OnMouseMoveEx(MouseEventArgs e)
        {
        }
        #endregion
        #region OnMouseClick
        /// 
        /// Called by top-level control to pass message into the grid
        /// element. To handle it override corresponding On - virtual method.
        /// 
        /// 
        internal virtual bool InternalMouseClick(MouseEventArgs e)
        {
            return (OnMouseClick(e));
        }
        /// 
        /// Called when mouse is clicked on the element.
        /// 
        /// 
        protected virtual bool OnMouseClick(MouseEventArgs e)
        {
            return (true);
        }
        #endregion
        #region OnMouseDoubleClick
        /// 
        /// Called by top-level control to pass message into the grid
        /// element. To handle it override corresponding On - virtual method.
        /// 
        /// 
        internal virtual bool InternalMouseDoubleClick(MouseEventArgs e)
        {
            return (OnMouseDoubleClick(e));
        }
        /// 
        /// Called when mouse is double clicked on the element.
        /// 
        /// 
        protected virtual bool OnMouseDoubleClick(MouseEventArgs e)
        {
            return (false);
        }
        #endregion
        #region OnMouseWheel
        /// 
        /// Called by top-level control to pass message into the grid
        /// element. To handle it override corresponding On - virtual method.
        /// 
        /// 
        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);
        }
        /// 
        /// Called when mousewheel is moved while over the element.
        /// 
        /// 
        protected virtual bool OnMouseWheel(MouseEventArgs e)
        {
            return (false);
        }
        #endregion
        #endregion
        #region Keyboard handling
        /// 
        /// Called by top-level control to pass message into the grid
        /// element. To handle it override corresponding On - virtual method.
        /// 
        /// 
        internal virtual void InternalKeyDown(Keys keyData)
        {
            OnKeyDown(keyData);
        }
        /// 
        /// Called when mouse button is pressed over the element.
        /// 
        /// 
        protected virtual void OnKeyDown(Keys keyData)
        {
        }
        #endregion
        #region OnResize
        internal virtual bool InternalOnResize(EventArgs e)
        {
            return (OnResize(e));
        }
        /// 
        /// Called when control is resized.
        /// 
        /// 
        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
        /// 
        /// Occurs when one of element visual styles has property changes.
        /// Default implementation invalidates visual appearance of element.
        /// 
        /// VisualStyle that changed.
        /// Event arguments.
        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
        /// 
        /// Exports the chart element to the specified file. The 
        /// specified file will be created and/or overwritten.
        /// 
        /// 
        /// 
        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);
                }
            }
        }
        /// 
        /// Exports the chart element to the specified stream.
        /// 
        /// 
        /// 
        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("");
                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
        /// 
        /// Imoprts the chart element from the given file path.
        /// 
        /// 
        /// 
        public void Import(string fileName)
        {
            if (File.Exists(fileName) == true)
            {
                using (FileStream stream = new
                    FileStream(fileName, FileMode.Open, FileAccess.Read))
                {
                    Import(stream);
                }
            }
        }
        /// 
        /// Imoprts the chart element from the given stream.
        /// 
        /// 
        /// 
        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
        /// 
        /// Default PropertyChanged processing
        /// 
        /// 
        /// invalidate
        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
    ///
    /// Specifies the ItemHitArea hit areas
    ///
    public enum ItemHitArea
    {
        ///
        /// None
        ///
        None,
        /// 
        /// Ancillary AxisX
        /// 
        InAncillaryAxisX,
        /// 
        /// Primary AxisX
        /// 
        InPrimaryAxisX,
        /// 
        /// Ancillary AxisY
        /// 
        InAncillaryAxisY,
        /// 
        /// Primary AxisX
        /// 
        InPrimaryAxisY,
        /// 
        /// ScrollBar ArrowIncrease
        /// 
        ArrowIncrease,
        /// 
        /// ScrollBar ArrowDecrease
        /// 
        ArrowDecrease,
        /// 
        /// ScrollBar TrackIncrease
        /// 
        TrackIncrease,
        /// 
        /// ScrollBar ArrowDecrease
        /// 
        TrackDecrease,
        /// 
        /// ScrollBar Thumb
        /// 
        Thumb,
        ///
        /// Content area
        ///
        InContent,
        ///
        /// Frame area
        ///
        InFrame,
        /// 
        /// PieSeriesPoint
        /// 
        InPieSeriesPoint,
        /// 
        /// Pie Center
        /// 
        InPieCenter,
        /// 
        /// Pie Ring Out (Out a ring level)
        /// 
        InPieRingOut,
        /// 
        /// In Markup area
        /// 
        InMarkup,
    }
    #endregion
}