using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using DevComponents.Charts.TextMarkup;
using DevComponents.DotNetBar.Charts.Style;
namespace DevComponents.DotNetBar.Charts
{
    /// 
    /// Represents the collection of ChartContainer objects.
    /// 
    [Editor("DevComponents.Charts.Design.ChartContainerCollectionEditor, DevComponents.Charts.Design, " +
            "Version=14.1.0.37, Culture=neutral,  PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
    public class ChartContainerCollection : CustomNamedCollection
    {
        public ChartContainerCollection()
        {
        }
        #region GetUniqueName
        public string GetUniqueName()
        {
            return (GetUniqueName("ChartCont"));
        }
        #endregion
    }
    /// 
    /// ChartContainer
    /// 
    public class ChartContainer : ChartVisualElement, ILegendData, IScrollable, IComparable
    {
        #region Private variables
        private States _States;
        private string _EmptyText;
        private BodyElement _EmptyTextMarkup;
        private ChartLegend _Legend;
        private ChartTitleCollection _Titles;
        private ScrollBarLite _VScrollBar;
        private ScrollBarLite _HScrollBar;
        private int _VScrollBarWidth = 9;
        private int _HScrollBarHeight = 9;
        private Rectangle _FrameBounds;         // Margin
        private Rectangle _ContentBounds;       // Content - chart container(s)
        private Rectangle _ContentBoundsEx;     // Content - extended content bounds
        private int _FillWeight = 100;
        private AutoSizeMode _AutoSizeMode = AutoSizeMode.NotSet;
        private Size _MinContentSize = new Size(100, 100);
        private Timer _AutoScrollTimer;
        private AutoScrollEnable _AutoScrollEnable;
        private Rectangle _ScrollRect;
        private bool _Panning;
        private int _HPanOffset;
        private int _VPanOffset;
        private ItemHitArea _HitArea;
        private ItemHitArea _MouseDownHitArea;
        private ContainerVisualStyles _ContainerVisualStyles;
        private EffectiveStyles _EffectiveContainerStyles;
        private int _MatrixDisplayOrder;
        private Rectangle _MatrixDisplayBounds;
        private int _SelectionUpdateCount = -1;
        #endregion
        public ChartContainer()
        {
            InitDefaultStates();
            SetupScrollBars();
            _EffectiveContainerStyles = new EffectiveStyles(this);
        }
        #region InitDefaultStates
        private void InitDefaultStates()
        {
            SetState(States.AutoGenSeriesCollection, true);
            SetState(States.EnablePanning, true);
            SetState(States.HScrollBarVisible, true);
            SetState(States.VScrollBarVisible, true);
        }
        #endregion
        #region Public properties
        #region AutoSizeMode
        ///
        /// Gets or sets the mode used to size the container (by FillWeight, etc).
        ///
        [DefaultValue(AutoSizeMode.NotSet), Category("Layout")]
        [Description("Indicates the mode used to size the container (by FillWeight, etc).")]
        public AutoSizeMode AutoSizeMode
        {
            get { return (_AutoSizeMode); }
            set
            {
                if (value != _AutoSizeMode)
                {
                    _AutoSizeMode = value;
                    OnPropertyChangedEx("AutoSizeMode", VisualChangeType.Layout);
                }
            }
        }
        #endregion
        #region ContainerVisualStyles
        /// 
        /// Gets or sets the visual styles for the container.
        /// 
        [Category("Style")]
        [Description("Indicates the visual styles for the container.")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public ContainerVisualStyles ContainerVisualStyles
        {
            get
            {
                if (_ContainerVisualStyles == null)
                {
                    _ContainerVisualStyles = new ContainerVisualStyles();
                    StyleVisualChangeHandler(null, _ContainerVisualStyles);
                }
                return (_ContainerVisualStyles);
            }
            set
            {
                if (_ContainerVisualStyles != value)
                {
                    ContainerVisualStyles oldValue = _ContainerVisualStyles;
                    _ContainerVisualStyles = value;
                    OnStyleChanged("ContainerVisualStyles", oldValue, value);
                    if (oldValue != null)
                        oldValue.Dispose();
                }
            }
        }
        #endregion
        #region ContentBounds
        /// 
        /// Gets the Content area bounding rectangle.
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Rectangle ContentBounds
        {
            get { return (_ContentBounds); }
            internal set { _ContentBounds = value; }
        }
        #endregion
        #region EffectiveContainerStyle
        /// 
        /// Gets a reference to the container's effective (cached, composite) styles.
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public EffectiveStyles EffectiveContainerStyles
        {
            get { return (_EffectiveContainerStyles); }
        }
        #endregion
        #region EmptyText
        /// 
        /// Gets or sets the Text to display when the container is empty.
        /// 
        [Browsable(true), Category("Appearance"), DefaultValue(null)]
        [Description("Indicates the Text to display when the container is empty.")]
        public string EmptyText
        {
            get { return (_EmptyText); }
            set
            {
                if (_EmptyText != value)
                {
                    _EmptyText = value;
                    EmptyTextMarkupChanged();
                    OnPropertyChangedEx("EmptyText", VisualChangeType.Render);
                }
            }
        }
        #endregion
        #region EnableEmptyTextMarkup
        /// 
        /// Gets or sets whether EmptyText markup support is enabled.
        /// 
        [DefaultValue(false), Category("Appearance")]
        [Description("Indicates whether EmptyText markup support is enabled.")]
        public bool EnableEmptyTextMarkup
        {
            get { return (TestState(States.EnableEmptyTextMarkup)); }
            set
            {
                if (EnableEmptyTextMarkup != value)
                {
                    SetState(States.EnableEmptyTextMarkup, value);
                    EmptyTextMarkupChanged();
                    OnPropertyChangedEx("EnableEmptyTextMarkup", VisualChangeType.Layout);
                }
            }
        }
        #region Markup support
        private void EmptyTextMarkupChanged()
        {
            _EmptyTextMarkup = null;
            if (EnableEmptyTextMarkup == true)
            {
                if (MarkupParser.IsMarkup(_EmptyText) == true)
                {
                    _EmptyTextMarkup = MarkupParser.Parse(_EmptyText);
                    if (_EmptyTextMarkup != null)
                        _EmptyTextMarkup.HyperLinkClick += EmptyTextMarkupLinkClick;
                }
            }
        }
        /// 
        /// Occurs when a text markup link is clicked
        /// 
        protected virtual void EmptyTextMarkupLinkClick(object sender, EventArgs e)
        {
            HyperLink link = sender as HyperLink;
            ChartControl.DoEmptyTextMarkupLinkClickEvent(this, link);
        }
        /// 
        /// Gets plain text without text-markup (if text-markup is used in EmptyText)
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public string EmptyTextPlainText
        {
            get { return (_EmptyTextMarkup != null ? _EmptyTextMarkup.PlainText : _EmptyText); }
        }
        #endregion
        #endregion
        #region EnablePanning
        /// 
        /// Gets or sets whether the container can be panned with the mouse.
        /// 
        [DefaultValue(true), Category("Behavior")]
        [Description("Indicates whether the container can be panned with the mouse.")]
        public bool EnablePanning
        {
            get { return (TestState(States.EnablePanning)); }
            set
            {
                if (value != EnablePanning)
                {
                    SetState(States.EnablePanning, value);
                    OnPropertyChanged("EnablePanning");
                }
            }
        }
        #endregion
        #region EnableSelection
        /// 
        /// Gets or sets whether the CONTAINER can be "selected" with the mouse.
        /// 
        [DefaultValue(false), Category("Behavior")]
        [Description("Indicates whether the CONTAINER can be \"selected\" with the mouse.")]
        public bool EnableSelection
        {
            get { return (TestState(States.EnableSelection)); }
            set
            {
                if (value != EnableSelection)
                {
                    SetState(States.EnableSelection, value);
                    OnPropertyChanged("EnableSelection");
                }
            }
        }
        #endregion
        #region FillWeight
        /// 
        /// Gets or sets a value which, when AutoSizeMode is Fill,
        /// represents the width of the container relative to the widths
        /// of other fill-mode containers (default value is 100).
        /// 
        [DefaultValue(100), Category("Layout")]
        [Description("Indicates a value which, when AutoSizeMode is Fill, represents the width of the containers relative to the widths of other fill-mode containers (default value is 100).")]
        public int FillWeight
        {
            get { return (_FillWeight); }
            set
            {
                if (value != _FillWeight)
                {
                    _FillWeight = value;
                    OnPropertyChangedEx("FillWeight", VisualChangeType.Layout);
                }
            }
        }
        #endregion
        #region FrameBounds
        /// 
        /// Gets the Frame area bounding rectangle.
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Rectangle FrameBounds
        {
            get { return (_FrameBounds); }
            internal set { _FrameBounds = value; }
        }
        #endregion
        #region HScrollBar
        ///
        /// Gets a reference to the containers’s horizontal scrollbar
        ///
        [Category("ScrollBar")]
        [Description("Indicates the container’s horizontal scrollbar.")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public ScrollBarLite HScrollBar
        {
            get { return (_HScrollBar); }
            internal set { _HScrollBar = value; }
        }
        #endregion
        #region HScrollBarHeight
        /// 
        /// Gets or sets the horizontal scrollBar height.
        /// 
        [DefaultValue(9), Category("ScrollBar")]
        [Description("Indicates the horizontal scrollBar height")]
        public int HScrollBarHeight
        {
            get { return (_HScrollBarHeight); }
            set
            {
                if (value != _HScrollBarHeight)
                {
                    if (value > 0)
                    {
                        _HScrollBarHeight = value;
                        OnPropertyChangedEx("HScrollBarHeight", VisualChangeType.Layout);
                    }
                }
            }
        }
        #endregion
        #region HScrollOffset
        ///
        /// Gets or sets the horizontal scrollbar offset.
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int HScrollOffset
        {
            get
            {
                if (_HScrollBar != null && _HScrollBar.Visible == true)
                    return (_HScrollBar.Value);
                return (0);
            }
            set { SetHScrollValue(value); }
        }
        #endregion
        #region HScrollBarVisible
        /// 
        /// Gets or sets whether Horizontal Scrollbar is shown if needed (due to content of the control exceeding available width).
        /// 
        [DefaultValue(true), Category("ScrollBar")]
        [Description("Indicates whether Horizontal Scrollbar is shown if needed (due to content of the control exceeding available width).")]
        public bool HScrollBarVisible
        {
            get { return (TestState(States.HScrollBarVisible)); }
            set
            {
                if (value != HScrollBarVisible)
                {
                    SetState(States.HScrollBarVisible, value);
                    InvalidateLayout();
                }
            }
        }
        #endregion
        #region IsSelected
        ///
        /// Gets or sets whether the container is selected.
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsSelected
        {
            get
            {
                ChartControl chartControl = ChartControl;
                if (chartControl != null)
                {
                    if (_SelectionUpdateCount == chartControl.SelectionUpdateCount)
                        return (TestState(States.IsSelected));
                    bool selected = chartControl.GetSelected(this);
                    SetState(States.IsSelected, selected);
                    _SelectionUpdateCount = chartControl.SelectionUpdateCount;
                }
                return (TestState(States.IsSelected));
            }
            set
            {
                if (value != IsSelected)
                {
                    SetState(States.IsSelected, value);
                    ChartControl chartControl = ChartControl;
                    if (chartControl != null)
                    {
                        chartControl.SetSelected(this, value);
                        InvalidateRender();
                    }
                }
            }
        }
        #endregion
        #region Legend
        /// 
        /// Gets or Sets the element Legend.
        /// 
        [Category("Legend")]
        [Description("Indicates the element Legend.")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public ChartLegend Legend
        {
            get
            {
                if (_Legend == null)
                    Legend = new ChartLegend();
                return (_Legend);
            }
            set
            {
                if (value != _Legend)
                {
                    if (_Legend != null)
                    {
                        _Legend.Parent = null;
                        _Legend.PropertyChanged -= LegendPropertyChanged;
                    }
                    _Legend = value;
                    if (_Legend != null)
                    {
                        _Legend.Parent = this;
                        _Legend.PropertyChanged += LegendPropertyChanged;
                    }
                }
            }
        }
        void LegendPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            InvalidateLayout();
        }
        #endregion
        #region MatrixAlignEndColumn
        ///
        /// Gets or sets whether the container's content ending X-offset is aligned 
        /// with other containers ending in the same ChartMatrix column.
        ///
        [DefaultValue(false), Category("Matrix")]
        [Description("Indicates whether the container's content ending X-offset is aligned with other containers ending in the same ChartMatrix column.")]
        public bool MatrixAlignEndColumn
        {
            get { return (TestState(States.MatrixAlignEndColumn)); }
            set
            {
                if (value != MatrixAlignEndColumn)
                {
                    SetState(States.MatrixAlignEndColumn, value);
                    OnPropertyChangedEx("MatrixAlignEndColumn", VisualChangeType.Layout);
                }
            }
        }
        #endregion
        #region MatrixAlignEndRow
        ///
        /// Gets or sets whether the container's content ending Y-offset is aligned 
        /// with other containers ending in the same ChartMatrix row.
        ///
        [DefaultValue(false), Category("Matrix")]
        [Description("Indicates whether the container's content ending Y-offset is aligned with other containers ending in the same ChartMatrix row.")]
        public bool MatrixAlignEndRow
        {
            get { return (TestState(States.MatrixAlignEndRow)); }
            set
            {
                if (value != MatrixAlignEndRow)
                {
                    SetState(States.MatrixAlignEndRow, value);
                    OnPropertyChangedEx("MatrixAlignEndRow", VisualChangeType.Layout);
                }
            }
        }
        #endregion
        #region MatrixAlignStartColumn
        ///
        /// Gets or sets whether the container's content starting X-offset is aligned 
        /// with other containers starting in the same ChartMatrix column.
        ///
        [DefaultValue(false), Category("Matrix")]
        [Description("Indicates whether the container's content starting X-offset is aligned with other containers starting in the same ChartMatrix column.")]
        public bool MatrixAlignStartColumn
        {
            get { return (TestState(States.MatrixAlignStartColumn)); }
            set
            {
                if (value != MatrixAlignStartColumn)
                {
                    SetState(States.MatrixAlignStartColumn, value);
                    OnPropertyChangedEx("MatrixAlignStartColumn", VisualChangeType.Layout);
                }
            }
        }
        #endregion
        #region MatrixAlignStartRow
        ///
        /// Gets or sets whether the container's content starting Y-offset is aligned 
        /// with other containers starting in the same ChartMatrix row.
        ///
        [DefaultValue(false), Category("Matrix")]
        [Description("Indicates whether the container's content starting Y-offset is aligned with other containers starting in the same ChartMatrix row.")]
        public bool MatrixAlignStartRow
        {
            get { return (TestState(States.MatrixAlignStartRow)); }
            set
            {
                if (value != MatrixAlignStartRow)
                {
                    SetState(States.MatrixAlignStartRow, value);
                    OnPropertyChangedEx("MatrixAlignStartRow", VisualChangeType.Layout);
                }
            }
        }
        #endregion
        #region MatrixDisplayBounds
        ///
        /// Gets or sets the containers matrix display bounds (in relative units of the matrix).
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Rectangle MatrixDisplayBounds
        {
            get { return (_MatrixDisplayBounds); }
            set
            {
                if (value != _MatrixDisplayBounds)
                {
                    _MatrixDisplayBounds = value;
                    OnPropertyChangedEx("MatrixDisplayBounds", VisualChangeType.Layout);
                }
            }
        }
        #endregion
        #region MatrixDisplayOrder
        ///
        /// Gets or sets the containers display order in the parent matrix layout
        /// (higher values are placed on top of lower values).
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int MatrixDisplayOrder
        {
            get { return (_MatrixDisplayOrder); }
            set
            {
                if (value != _MatrixDisplayOrder)
                {
                    _MatrixDisplayOrder = value;
                    OnPropertyChangedEx("MatrixDisplayOrder", VisualChangeType.Layout);
                }
            }
        }
        #endregion
        #region MinContentSize
        /// 
        /// Gets or sets the minimum size of the content area of the chart.
        /// 
        [Category("Layout")]
        [Description("Indicates the minimum size of the content area of the chart.")]
        public Size MinContentSize
        {
            get { return (_MinContentSize); }
            set
            {
                if (value != _MinContentSize)
                {
                    _MinContentSize = value;
                    OnPropertyChangedEx("MinContentSize", VisualChangeType.Layout);
                }
            }
        }
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        internal virtual bool ShouldSerializeMinContentSize()
        {
            return (_MinContentSize.Width != 100 || _MinContentSize.Height != 100);
        }
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        internal virtual void ResetMinContentSize()
        {
            MinContentSize = new Size(100, 100);
        }
        #endregion
        #region ScrollBounds
        /// 
        /// Gets the Scrollable bounds.
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual Rectangle ScrollBounds
        {
            get { return (_ContentBounds); }
        }
        #endregion
        #region ScrollBoundsEx
        /// 
        /// Gets the extended Scrollable bounds.
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual Rectangle ScrollBoundsEx
        {
            get { return (_ContentBoundsEx); }
        }
        #endregion
        #region ScrollBoundsOffset
        ///
        /// Gets the current scrollbar offset
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Point ScrollBoundsOffset
        {
            get { return (new Point(HScrollOffset, VScrollOffset)); }
        }
        #endregion
        #region Titles
        /// 
        /// Gets or Sets a reference to the collection of Titles
        /// 
        [Category("Appearance")]
        [Description("Indicates the collection of Titles.")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public ChartTitleCollection Titles
        {
            get
            {
                if (_Titles == null)
                {
                    _Titles = new ChartTitleCollection();
                    _Titles.CollectionChanged += TitlesCollectionChanged;
                }
                return (_Titles);
            }
            internal set
            {
                if (_Titles != null)
                    _Titles.CollectionChanged -= TitlesCollectionChanged;
                _Titles = value;
                if (_Titles != null)
                    _Titles.CollectionChanged += TitlesCollectionChanged;
            }
        }
        #region TitlesCollectionChanged
        void TitlesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    foreach (ChartTitle title in e.NewItems)
                        title.Parent = this;
                    break;
                case NotifyCollectionChangedAction.Replace:
                    foreach (ChartTitle title in e.OldItems)
                        title.Parent = null;
                    foreach (ChartTitle title in e.NewItems)
                        title.Parent = this;
                    break;
                case NotifyCollectionChangedAction.Remove:
                    foreach (ChartTitle title in e.OldItems)
                        title.Parent = null;
                    break;
            }
            InvalidateLayout();
        }
        #endregion
        #endregion
        #region VScrollBar
        ///
        /// Gets a reference to the container’s vertical scrollbar
        ///
        [Category("ScrollBar")]
        [Description("Indicates the container’s vertical scrollbar.")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public ScrollBarLite VScrollBar
        {
            get { return (_VScrollBar); }
        }
        #endregion
        #region VScrollBarWidth
        /// 
        /// Gets or sets the vertical scrollBar width.
        /// 
        [DefaultValue(9), Category("ScrollBar")]
        [Description("Indicates the vertical scrollBar width")]
        public int VScrollBarWidth
        {
            get { return (_VScrollBarWidth); }
            set
            {
                if (value != _VScrollBarWidth)
                {
                    if (value > 0)
                    {
                        _VScrollBarWidth = value;
                        OnPropertyChangedEx("VScrollBarWidth", VisualChangeType.Layout);
                    }
                }
            }
        }
        #endregion
        #region VScrollOffset
        ///
        /// Gets the vertical scrollbar offset
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int VScrollOffset
        {
            get
            {
                if (_VScrollBar != null && _VScrollBar.Visible == true)
                    return (_VScrollBar.Value);
                return (0);
            }
            set { SetVScrollValue(value); }
        }
        #endregion
        #region VScrollBarVisible
        /// 
        /// Gets or sets whether Vertical Scrollbar is shown when needed (due to the content area exceeding available height).
        /// 
        [DefaultValue(true), Category("ScrollBar")]
        [Description("Indicates whether Vertical Scrollbar is shown when needed (due to the content area exceeding available height)")]
        public bool VScrollBarVisible
        {
            get { return (TestState(States.VScrollBarVisible)); }
            set
            {
                if (value != VScrollBarVisible)
                {
                    SetState(States.VScrollBarVisible, value);
                    InvalidateLayout();
                }
            }
        }
        #endregion
        #endregion
        #region Internal properties
        #region ContentBoundsEx
        internal Rectangle ContentBoundsEx
        {
            get { return (_ContentBoundsEx); }
            set { _ContentBoundsEx = value; }
        }
        #endregion
        #region EmptyTextMarkup
        internal BodyElement EmptyTextMarkup
        {
            get { return (_EmptyTextMarkup); }
            set { _EmptyTextMarkup = value; }
        }
        #endregion
        #region HitArea
        internal ItemHitArea HitArea
        {
            get { return (_HitArea); }
            set { _HitArea = value; }
        }
        #endregion
        #region IsSubPanel
        /// 
        /// Gets whether the ChartPanel is a subordinate / nested panel.
        /// 
        internal bool IsSubPanel
        {
            get { return (Parent != null); }
        }
        #endregion
        #region MatrixColumnAligned
        /// 
        /// Gets whether the ChartContainer column was MatrixAligned.
        /// 
        internal bool MatrixColumnAligned
        {
            get { return (TestState(States.MatrixColumnAligned)); }
            set { SetState(States.MatrixColumnAligned, value); }
        }
        #endregion
        #region MatrixRowAligned
        /// 
        /// Gets whether the ChartContainer row was MatrixAligned.
        /// 
        internal bool MatrixRowAligned
        {
            get { return (TestState(States.MatrixRowAligned)); }
            set { SetState(States.MatrixRowAligned, value); }
        }
        #endregion
        #region MouseDownHitArea
        internal ItemHitArea MouseDownHitArea
        {
            get { return (_MouseDownHitArea); }
            set { _MouseDownHitArea = value; }
        }
        #endregion
        #endregion
        #region MeasureOverride
        protected override void MeasureOverride(ChartLayoutInfo layoutInfo)
        {
            if (Legend.Visible == true)
                Legend.Measure(layoutInfo);
            foreach (ChartTitle title in Titles)
            {
                if (title.Visible == true)
                    title.Measure(layoutInfo);
            }
        }
        #endregion
        #region ArrangeOverride
        protected override void ArrangeOverride(ChartLayoutInfo layoutInfo)
        {
            if (Legend.Visible == true)
                Legend.Arrange(layoutInfo);
            foreach (ChartTitle title in Titles)
            {
                if (title.Visible == true)
                    title.Arrange(layoutInfo);
            }
            UpdateScrollBars(layoutInfo);
        }
        #endregion
        #region RenderOverride
        protected override void RenderOverride(ChartRenderInfo renderInfo)
        {
            Graphics g = renderInfo.Graphics;
            // Render Titles
            foreach (ChartTitle title in Titles)
            {
                if (title.Visible == true)
                    title.Render(renderInfo);
            }
            // Render the Legend
            if (Legend.Visible == true)
                Legend.Render(renderInfo);
        }
        #endregion
        #region RenderTextMarkup
        internal void RenderTextMarkup(Graphics g,
            Font font, Color textColor, Alignment alignment, Rectangle r)
        {
            if (textColor.IsEmpty)
                textColor = Color.Black;
            MarkupDrawContext d =
                new MarkupDrawContext(g, font, textColor, false);
            _EmptyTextMarkup.Arrange(new Rectangle(Point.Empty, r.Size), d);
            Size size = _EmptyTextMarkup.Bounds.Size;
            switch (alignment)
            {
                case Alignment.NotSet:
                case Alignment.MiddleLeft:
                case Alignment.MiddleCenter:
                case Alignment.MiddleRight:
                    if (r.Height > size.Height)
                        r.Y += (r.Height - size.Height) / 2;
                    break;
                case Alignment.BottomLeft:
                case Alignment.BottomCenter:
                case Alignment.BottomRight:
                    if (r.Height > size.Height)
                        r.Y = r.Bottom - size.Height;
                    break;
            }
            _EmptyTextMarkup.Bounds = new Rectangle(r.Location, size);
            Region oldClip = g.Clip;
            try
            {
                g.SetClip(r, CombineMode.Intersect);
                _EmptyTextMarkup.Render(d);
            }
            finally
            {
                g.Clip = oldClip;
            }
        }
        #endregion
        #region RenderEmptyText
        protected void RenderEmptyText(
            Graphics g, ContainerVisualStyle style, Rectangle bounds)
        {
            if (String.IsNullOrEmpty(EmptyText) == false)
            {
                if (EmptyTextMarkup != null)
                {
                    RenderTextMarkup(g, style.Font,
                        style.TextColor, style.Alignment, bounds);
                }
                else
                {
                    eTextFormat tf = style.GetTextFormatFlags();
                    TextDrawing.DrawString(g,
                        EmptyText, style.Font, style.TextColor, bounds, tf);
                }
            }
        }
        #endregion
        #region RenderScrollbars
        protected void RenderScrollbars(ChartRenderInfo renderInfo)
        {
            Graphics g = renderInfo.Graphics;
            if (HScrollBar.Visible == true && VScrollBar.Visible == true)
            {
                ScrollBarVisualStyle style = VScrollBar.GetEffectiveStyle();
                Rectangle r = HScrollBar.Bounds;
                r.X = VScrollBar.Bounds.X;
                r.Width = VScrollBar.Width;
                using (Brush br = style.TrackBackground.GetBrush(r))
                    g.FillRectangle(br, r);
                using (Pen pen = new Pen(style.BorderColor))
                    g.DrawRectangle(pen, r);
            }
            if (HScrollBar.Visible == true)
                HScrollBar.Render(renderInfo);
            if (VScrollBar.Visible == true)
                VScrollBar.Render(renderInfo);
        }
        #endregion
        #region Mouse handling
        #region OnMouseEnter
        protected override bool OnMouseEnter(EventArgs e)
        {
            base.OnMouseEnter(e);
            InvalidateRender();
            return (true);
        }
        #endregion
        #region OnMouseLeave
        protected override bool OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            InvalidateRender();
            return (true);
        }
        #endregion
        #region OnMouseMove
        protected override bool OnMouseMove(MouseEventArgs e)
        {
            _HitArea = GetHitArea(e.Location);
            if (IsMouseDown == true)
                return (OnMouseDownMove(e));
            if (_HitArea == ItemHitArea.InContent)
            {
                if (EmptyTextMarkup != null)
                {
                    ChartControl.SetChartCursor = true;
                    EmptyTextMarkup.MouseMove(ChartControl, e);
                    ChartControl.SetChartCursor = false;
                    if (EmptyTextMarkup.MouseOverElement != null)
                    {
                        if (EmptyTextMarkup.MouseOverElement is HyperLink)
                            return (true);
                    }
                }
                if (EnablePanning == true &&
                    (HScrollBar.Enabled == true || VScrollBar.Enabled == true))
                {
                    ChartCursor = OpenHandCursor;
                    return (true);
                }
            }
            ChartCursor = Cursors.Default;
            return (false);
        }
        #region OnMouseDownMove
        private bool OnMouseDownMove(MouseEventArgs e)
        {
            if (_Panning == true)
            {
                ChartCursor = ClosedHandCursor;
                if (HScrollBar.Enabled == true)
                    HScrollOffset = _HPanOffset + (MouseDownPoint.X - e.Location.X);
                if (VScrollBar.Enabled == true)
                {
                    int n = (MouseDownPoint.Y - e.Location.Y);
                    if (VScrollBar.Inverted == true)
                        VScrollOffset = _VPanOffset - n;
                    else
                        VScrollOffset = _VPanOffset + n;
                }
            }
            return (true);
        }
        #endregion
        #endregion
        #region OnMouseDown
        protected override bool OnMouseDown(MouseEventArgs e)
        {
            ChartControl.Focus();
            UpdateSelection(e);
            return (OnMouseDownEx(e));
        }
        protected override bool OnMouseDownEx(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            MouseDownHitArea = _HitArea;
            if (EmptyTextMarkup != null)
            {
                if (EmptyTextMarkup.MouseOverElement != null)
                {
                    EmptyTextMarkup.MouseDown(ChartControl, e);
                    return (true);
                }
            }
            if (_HitArea == ItemHitArea.InContent)
            {
                if (EnablePanning == true &&
                    (HScrollBar.Visible == true || VScrollBar.Visible == true))
                {
                    _HPanOffset = HScrollOffset;
                    _VPanOffset = VScrollOffset;
                    _Panning = true;
                    ChartCursor = ClosedHandCursor;
                    ChartControl.PostInternalMouseMove();
                    ChartControl.CapturedItem = this;
                    return (true);
                }
            }
            return (false);
        }
        #region UpdateSelection
        private void UpdateSelection(MouseEventArgs e)
        {
            ChartContainer parent = Parent as ChartContainer;
            if (parent != null && parent.EnableSelection == true)
            {
                if (IsSelected == false ||
                    ((e.Button & MouseButtons.Left) == MouseButtons.Left))
                {
                    ChartControl chartControl = ChartControl;
                    if (chartControl != null)
                    {
                        bool ctrlKey = ((Control.ModifierKeys & Keys.Control) == Keys.Control);
                        if (ctrlKey == true)
                        {
                            chartControl.SetSelected(this, !IsSelected);
                        }
                        else
                        {
                            chartControl.ClearAllSelected();
                            chartControl.SetSelected(this, true);
                        }
                    }
                }
            }
        }
        #endregion
        #endregion
        #region OnMouseUp
        protected override bool OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            if (EmptyTextMarkup != null)
            {
                if (EmptyTextMarkup.MouseOverElement != null)
                    EmptyTextMarkup.Click(ChartControl);
            }
            if (_Panning == true)
            {
                _Panning = false;
                ChartControl.CapturedItem = null;
            }
            return (true);
        }
        #endregion
        #region OnMouseWheel
        protected override bool OnMouseWheel(MouseEventArgs e)
        {
            if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
                return (OnHorizontalMouseWheel(e));
            return (OnVerticalMouseWheel(e));
        }
        #region OnHorizontalMouseWheel
        private bool OnHorizontalMouseWheel(MouseEventArgs e)
        {
            if (HScrollBar.Enabled == true)
            {
                if ((e.Delta < 0 && HScrollBar.IsAtMaxumum == false) ||
                    (e.Delta > 0 && HScrollBar.IsAtMinumum == false))
                {
                    SetHWheelValue(-e.Delta);
                    return (true);
                }
            }
            return (false);
        }
        #region SetHWheelValue
        private void SetHWheelValue(int delta)
        {
            int value = delta * SystemInformation.MouseWheelScrollLines / 120;
            value *= HScrollBar.SmallChange;
            value += HScrollBar.Value;
            SetHScrollValue(value);
        }
        #endregion
        #endregion
        #region OnVerticalMouseWheel
        private bool OnVerticalMouseWheel(MouseEventArgs e)
        {
            if (VScrollBar.Enabled == true)
            {
                if (VScrollBar.Inverted == true)
                {
                    if ((e.Delta < 0 && VScrollBar.IsAtMinumum == false) ||
                        (e.Delta > 0 && VScrollBar.IsAtMaxumum == false))
                    {
                        SetVWheelValue(e.Delta);
                        return (true);
                    }
                }
                else
                {
                    if ((e.Delta < 0 && VScrollBar.IsAtMaxumum == false) ||
                        (e.Delta > 0 && VScrollBar.IsAtMinumum == false))
                    {
                        SetVWheelValue(-e.Delta);
                        return (true);
                    }
                }
            }
            return (false);
        }
        #region SetVWheelValue
        private void SetVWheelValue(int delta)
        {
            int value = delta * SystemInformation.MouseWheelScrollLines / 120;
            value *= VScrollBar.SmallChange;
            value += VScrollBar.Value;
            SetVScrollValue(value);
        }
        #endregion
        #endregion
        #endregion
        #endregion
        #region Scrollbar support
        #region SetupScrollBars
        private void SetupScrollBars()
        {
            _VScrollBar = new VScrollBarLite();
            _VScrollBar.Parent = this;
            _VScrollBar.Width = Dpi.Width(VScrollBarWidth);
            _HScrollBar = new HScrollBarLite();
            _HScrollBar.Parent = this;
            _HScrollBar.Height = Dpi.Height(HScrollBarHeight);
            _HScrollBar.Visible = false;
            _VScrollBar.Visible = false;
        }
        #endregion
        #region UpdateScrollBars
        private void UpdateScrollBars(ChartLayoutInfo layoutInfo)
        {
            Rectangle cbounds = ScrollBounds;
            Rectangle cboundsEx = ScrollBoundsEx;
            EnableHScrollBar(cbounds, cboundsEx);
            EnableVScrollBar(cbounds, cboundsEx);
            if (_HScrollBar.Enabled == true)
            {
                int widthEx = cboundsEx.Width;
                _HScrollBar.SmallChange = cbounds.Width / 20;
                _HScrollBar.Maximum = Math.Max(0, widthEx);
                _HScrollBar.LargeChange = Math.Min(cbounds.Width, _HScrollBar.Maximum);
                if (_HScrollBar.Value + _HScrollBar.LargeChange > _HScrollBar.Maximum)
                    _HScrollBar.Value = _HScrollBar.Maximum - _HScrollBar.LargeChange;
                _HScrollBar.Arrange(layoutInfo);
            }
            if (_VScrollBar.Enabled == true)
            {
                int heightEx = cboundsEx.Height;
                _VScrollBar.SmallChange = cbounds.Height / 20;
                _VScrollBar.Maximum = Math.Max(0, heightEx);
                _VScrollBar.LargeChange = Math.Min(cbounds.Height, _VScrollBar.Maximum);
                if (_VScrollBar.Value + _VScrollBar.LargeChange > _VScrollBar.Maximum)
                    _VScrollBar.Value = _VScrollBar.Maximum - _VScrollBar.LargeChange;
                _VScrollBar.Arrange(layoutInfo);
            }
        }
        #region EnableHScrollBar
        private void EnableHScrollBar(Rectangle cbounds, Rectangle cboundsEx)
        {
            bool enable = (HScrollBarVisible == true) &&
                (cboundsEx.Width > cbounds.Width);
            if ((cbounds.Height < _HScrollBar.Height + 4) || cbounds.Width <= 0)
                enable = false;
            if (enable == true)
            {
                _HScrollBar.Location = new
                    Point(cbounds.Left, cbounds.Bottom - _HScrollBar.Height - 1);
                int n = cbounds.Width - 1;
                if (_VScrollBar.Visible == true)
                    n -= _VScrollBar.Width;
                _HScrollBar.Width = n;
                _HScrollBar.Height = Dpi.Height(HScrollBarHeight);
            }
            else
            {
                _HScrollBar.Value = 0;
            }
            _HScrollBar.Enabled = enable;
            _HScrollBar.Visible = enable;
        }
        #endregion
        #region EnableVScrollBar
        private void EnableVScrollBar(Rectangle cbounds, Rectangle cboundsEx)
        {
            bool enable = (VScrollBarVisible == true) &&
                (cboundsEx.Height > cbounds.Height);
            if (cbounds.Height <= 0 || (cbounds.Width < _VScrollBar.Width + 4))
                enable = false;
            if (enable == true)
            {
                _VScrollBar.Location = new
                    Point(cbounds.Right - _VScrollBar.Width - 1, cbounds.Top);
                _VScrollBar.Height = cbounds.Height - 1;
                if (_HScrollBar.Visible == true)
                    _VScrollBar.Height -= _HScrollBar.Height;
                _VScrollBar.Width = Dpi.Width(VScrollBarWidth);
            }
            else
            {
                _VScrollBar.Value = 0;
            }
            _VScrollBar.Enabled = enable;
            _VScrollBar.Visible = enable;
        }
        #endregion
        #endregion
        #region SetVScrollValue
        internal void SetVScrollValue(int value)
        {
            if (_VScrollBar.Visible == true)
            {
                int oldValue = _VScrollBar.Value;
                value = Math.Max(value, 0);
                value = Math.Min(value, _VScrollBar.Maximum);
                _VScrollBar.Value = value;
            }
        }
        #endregion
        #region SetHScrollValue
        internal void SetHScrollValue(int value)
        {
            if (_HScrollBar.Visible == true)
            {
                int oldValue = _HScrollBar.Value;
                value = Math.Max(value, 0);
                value = Math.Min(value, _HScrollBar.Maximum);
                _HScrollBar.Value = value;
            }
        }
        #endregion
        #region AutoScrolling support
        #region EnableAutoScrolling
        internal void EnableAutoScrolling(
            AutoScrollEnable enable, Rectangle scrollRect)
        {
            if (ChartControl.Focused == true)
            {
                _AutoScrollEnable = enable;
                if ((_HScrollBar != null && _HScrollBar.Visible == true) ||
                    (_VScrollBar != null && _VScrollBar.Visible == true))
                {
                    _ScrollRect = scrollRect;
                    if (_AutoScrollTimer == null)
                    {
                        _AutoScrollTimer = new Timer();
                        _AutoScrollTimer.Interval = 10;
                        _AutoScrollTimer.Tick += AutoScrollTimerTick;
                        _AutoScrollTimer.Start();
                    }
                }
            }
        }
        #endregion
        #region DisableAutoScrolling
        internal void DisableAutoScrolling()
        {
            if (_AutoScrollTimer != null)
            {
                _AutoScrollTimer.Stop();
                _AutoScrollTimer.Tick -= AutoScrollTimerTick;
                _AutoScrollTimer = null;
            }
        }
        #endregion
        #region AutoScrollTimerTick
        private void AutoScrollTimerTick(object sender, EventArgs e)
        {
            Point pt = ChartControl.PointToClient(Cursor.Position);
            Rectangle t = _ScrollRect;
            if ((_AutoScrollEnable & AutoScrollEnable.Horizontal) == AutoScrollEnable.Horizontal &&
                (_HScrollBar != null && _HScrollBar.Visible == true))
            {
                int dx = (pt.X < t.X)
                    ? ScrollAmount(pt.X - t.X)
                    : (pt.X >= t.Right) ? ScrollAmount(pt.X - t.Right) : 0;
                SetHScrollValue(_HScrollBar.Value + dx);
            }
            if ((_AutoScrollEnable & AutoScrollEnable.Vertical) == AutoScrollEnable.Vertical &&
                (_VScrollBar != null && _VScrollBar.Visible == true))
            {
                int dy = (pt.Y < t.Top)
                    ? ScrollAmount(pt.Y - t.Top)
                    : (pt.Y >= t.Bottom) ? ScrollAmount(pt.Y - t.Bottom) : 0;
                SetVScrollValue(_VScrollBar.Value + dy);
            }
        }
        #endregion
        #region ScrollAmount
        private int ScrollAmount(int delta)
        {
            int n = Math.Abs(delta);
            int amt = 1 << ((n / 16) + 1);
            return (delta < 0 ? -amt : amt);
        }
        #endregion
        #endregion
        #endregion
        #region EnsureVisible
        /// 
        /// Ensures the container is visible on screen, and optionally
        /// centered (if possible).
        /// 
        /// 
        public virtual void EnsureVisible(bool center)
        {
            ChartContainer parent = Parent as ChartContainer;
            if (parent != null)
                parent.EnsureVisible(this, center);
        }
        /// 
        /// Ensures that the given container "item" is visible
        /// on screen, and optionally centered (if possible).
        /// 
        /// 
        public virtual void EnsureVisible(ChartContainer item, bool center)
        {
            Rectangle bounds = ContentBounds;
            bounds.X += HScrollOffset;
            if (VScrollBar.Inverted == true)
                bounds.Y -= VScrollOffset;
            else
                bounds.Y += VScrollOffset;
            if (HScrollBar.Enabled == true)
                bounds.Width -= VScrollBar.Width;
            if (VScrollBar.Enabled == true)
                bounds.Height -= HScrollBar.Height;
            bounds.Width -= Dpi.Width4;
            bounds.Height -= Dpi.Height4;
            Rectangle ibounds = item.FrameBounds;
            if (bounds.Contains(ibounds) == false)
            {
                if (HScrollBar.Enabled == true)
                {
                    if (center == true)
                    {
                        int x = (bounds.X + bounds.Right) / 2 - (ibounds.Width / 2);
                        SetHScrollValue(ibounds.X - x);
                    }
                    else
                    {
                        int x = ibounds.X;
                        if (ibounds.Right > bounds.Right)
                            x -= (ibounds.Right - bounds.Right);
                        if (x < bounds.X)
                            x = bounds.X;
                        SetHScrollValue(HScrollOffset + (ibounds.X - x));
                    }
                }
                if (VScrollBar.Enabled == true)
                {
                    if (center == true)
                    {
                        int y = (bounds.Y + bounds.Bottom) / 2;
                        y -= (ibounds.Height / 2);
                        SetVScrollValue(ibounds.Y - y);
                    }
                    else
                    {
                        int y = ibounds.Y;
                        if (ibounds.Bottom > bounds.Bottom)
                            y -= (ibounds.Bottom - bounds.Bottom);
                        if (y < bounds.Y)
                            y = bounds.Y;
                        SetVScrollValue(VScrollOffset + (ibounds.Y - y));
                    }
                }
            }
            ChartContainer parent = Parent as ChartContainer;
            if (parent != null)
                parent.EnsureVisible(this, center);
        }
        #endregion
        #region GetDisplayBounds
        /// 
        /// Gets the "displayBounds" of the given rectangle (scroll
        /// adjusted bounds).
        /// 
        /// 
        /// 
        public Rectangle GetDisplayBounds(Rectangle bounds)
        {
            bounds.X -= HScrollOffset;
            if (VScrollBar.Inverted == true)
                bounds.Y += VScrollOffset;
            else
                bounds.Y -= VScrollOffset;
            return (bounds);
        }
        #endregion
        #region GetElementAt
        /// 
        /// Gets the element at the given Point.
        /// 
        /// 
        /// 
        public override ChartVisualElement GetElementAt(Point pt)
        {
            if (InScrollBar(HScrollBar, pt))
                return (HScrollBar);
            if (InScrollBar(VScrollBar, pt))
                return (VScrollBar);
            foreach (ChartTitle title in Titles)
            {
                if (title.Visible == true)
                {
                    if (title.Bounds.Contains(pt))
                        return (title);
                }
            }
            if (Legend.Visible == true)
            {
                if (Legend.FrameBounds.Contains(pt))
                {
                    ChartVisualElement item = Legend.GetElementAt(pt);
                    return (item ?? Legend);
                }
            }
            return (null);
        }
        #region InScrollBar
        private bool InScrollBar(ScrollBarLite scrollBar, Point pt)
        {
            if (scrollBar != null && scrollBar.Visible == true)
            {
                if (scrollBar.Bounds.Contains(pt))
                    return (true);
            }
            return (false);
        }
        #endregion
        #endregion
        #region GetHitArea
        /// 
        /// Gets the HitArea for the given Point.
        /// 
        /// 
        /// 
        public override ItemHitArea GetHitArea(Point pt)
        {
            Rectangle contentBounds = GetScrollBounds(ContentBounds);
            if (contentBounds.Contains(pt))
                return (ItemHitArea.InContent);
            Rectangle frameBounds = GetScrollBounds(FrameBounds);
            if (frameBounds.Contains(pt))
                return (ItemHitArea.InFrame);
            return (ItemHitArea.None);
        }
        #endregion
        #region GetTitleByName
        /// 
        /// Gets the defined Title with the given name.
        /// 
        /// 
        /// ChartTitle or null
        public ChartTitle GetTitleByName(string name)
        {
            return (Titles[name]);
        }
        #endregion
        #region Style Support
        #region GetEffectiveContainerStyle
        internal ContainerVisualStyle GetEffectiveContainerStyle()
        {
            StyleState state = GetStyleState();
            return (EffectiveContainerStyles[state]);
        }
        #endregion
        #region GetStyleState
        private StyleState GetStyleState()
        {
            StyleState state = StyleState.Default;
            if (IsMouseOver == true)
                state |= StyleState.MouseOver;
            if (IsSelected == true)
                state |= StyleState.Selected;
            return (state);
        }
        #endregion
        #region ApplyStyles
        public override void ApplyStyles(BaseVisualStyle style, StyleType cs)
        {
            base.ApplyStyles(style);
            ContainerVisualStyle cstyle = style as ContainerVisualStyle;
            if (cstyle != null)
            {
                ApplyParentStyles(cstyle, Parent as ChartContainer, cs);
                cstyle.ApplyStyle(ContainerVisualStyles[cs]);
            }
        }
        #region ApplyParentStyles (ChartContainerVisualStyles)
        private void ApplyParentStyles(
            ContainerVisualStyle cstyle, ChartContainer item, StyleType cs)
        {
            if (item != null)
            {
                ApplyParentStyles(cstyle, item.Parent as ChartContainer, cs);
                ChartPanel panel = item as ChartPanel;
                if (panel != null)
                {
                    if (panel.DefaultVisualStyles.ContainerVisualStyles != null)
                        cstyle.ApplyStyle(panel.DefaultVisualStyles.ContainerVisualStyles[cs]);
                }
            }
            else
            {
                ChartControl chartControl = ChartControl;
                if (chartControl.BaseVisualStyles.ContainerVisualStyles != null)
                    cstyle.ApplyStyle(chartControl.BaseVisualStyles.ContainerVisualStyles[cs]);
                if (chartControl.DefaultVisualStyles.ContainerVisualStyles != null)
                    cstyle.ApplyStyle(chartControl.DefaultVisualStyles.ContainerVisualStyles[cs]);
            }
        }
        #endregion
        #endregion
        #region ApplyDefaults
        public override void ApplyDefaults(BaseVisualStyle style, StyleType cs)
        {
            ContainerVisualStyle cstyle = style as ContainerVisualStyle;
            if (cstyle != null)
            {
                if (cstyle.BorderPattern == null)
                    cstyle.BorderPattern = new BorderPattern(LinePattern.Solid);
                if (cstyle.DropShadow.Enabled == Tbool.NotSet)
                    cstyle.DropShadow.Enabled = Tbool.False;
            }
            base.ApplyDefaults(style, cs);
        }
        #endregion
        #region InvalidateStyle
        ///
        ///Invalidate the cached Style
        ///
        public void InvalidateStyle()
        {
            ClearEffectiveStyles();
        }
        #endregion
        #region ClearEffectiveStyles
        protected override void ClearEffectiveStyles()
        {
            _EffectiveContainerStyles.InvalidateStyles();
            if (_VScrollBar != null)
                _VScrollBar.InvalidateStyle();
            if (_HScrollBar != null)
                _HScrollBar.InvalidateStyle();
        }
        #endregion
        #endregion
        #region ILegendData
        #region GetLegendItems
        public virtual List GetLegendData()
        {
            return (null);
        }
        #endregion
        #endregion
        #region CompareTo
        public int CompareTo(object obj)
        {
            ChartContainer cobj = obj as ChartContainer;
            if (cobj != null)
            {
                if (this.Equals(cobj) == true)
                    return (0);
            }
            return (-1);
        }
        #endregion
        #region Copy/CopyTo
        public override ChartVisualElement Copy()
        {
            ChartContainer copy = new ChartContainer();
            CopyTo(copy);
            return (copy);
        }
        public override void CopyTo(ChartVisualElement copy)
        {
            ChartContainer c = copy as ChartContainer;
            if (c != null)
            {
                base.CopyTo(c);
                c.AutoSizeMode = AutoSizeMode;
                c.ContainerVisualStyles = (_ContainerVisualStyles != null) ? ContainerVisualStyles.Copy() : null;
                c.EmptyText = EmptyText;
                c.EnableEmptyTextMarkup = EnableEmptyTextMarkup;
                c.EnablePanning = EnablePanning;
                c.EnableSelection = EnableSelection;
                c.FillWeight = FillWeight;
                c.HScrollBarHeight = HScrollBarHeight;
                c.HScrollBarVisible = HScrollBarVisible;
                c.Legend = (_Legend != null) ? (ChartLegend)Legend.Copy() : null;
                c.MatrixAlignEndColumn = MatrixAlignEndColumn;
                c.MatrixAlignEndRow = MatrixAlignEndRow;
                c.MatrixAlignStartColumn = MatrixAlignStartColumn;
                c.MatrixAlignStartRow = MatrixAlignStartRow;
                c.MatrixDisplayBounds = MatrixDisplayBounds;
                c.MatrixDisplayOrder = MatrixDisplayOrder;
                c.MinContentSize = MinContentSize;
                c.Titles.Clear();
                foreach (ChartTitle title in Titles)
                    c.Titles.Add((ChartTitle)title.Copy());
                c.VScrollBarWidth = VScrollBarWidth;
                c.VScrollBarVisible = VScrollBarVisible;
            }
        }
        #endregion
        #region GetSerialData
        internal override SerialElementCollection GetSerialData(string serialName)
        {
            SerialElementCollection sec = new SerialElementCollection();
            if (serialName != null)
            {
                if (serialName.Equals("") == true)
                    serialName = "ChartContainer";
                sec.AddStartElement(serialName);
            }
            sec.AddValue("AutoSizeMode", AutoSizeMode, AutoSizeMode.NotSet);
            if (_ContainerVisualStyles != null && _ContainerVisualStyles.IsEmpty == false)
                sec.AddElement(_ContainerVisualStyles.GetSerialData("ContainerVisualStyles"));
            sec.AddValue("EmptyText", EmptyText, null);
            sec.AddValue("EnableEmptyTextMarkup", EnableEmptyTextMarkup, false);
            sec.AddValue("EnablePanning", EnablePanning, true);
            sec.AddValue("EnableSelection", EnableSelection, false);
            sec.AddValue("FillWeight", FillWeight, 100);
            sec.AddValue("HScrollBarHeight", HScrollBarHeight, 9);
            sec.AddValue("HScrollBarVisible", HScrollBarVisible, true);
            if (_HScrollBar != null)
                sec.AddElement(_HScrollBar.GetSerialData("HScrollBar"));
            if (_Legend != null)
                sec.AddElement(_Legend.GetSerialData("Legend"));
            sec.AddValue("MatrixAlignEndColumn", MatrixAlignEndColumn, false);
            sec.AddValue("MatrixAlignEndRow", MatrixAlignEndRow, false);
            sec.AddValue("MatrixAlignStartColumn", MatrixAlignStartColumn, false);
            sec.AddValue("MatrixAlignStartRow", MatrixAlignStartRow, false);
            ChartPanel panel = Parent as ChartPanel;
            if (panel == null || panel.AutoFillChartMatrix == false) 
            {
                if (_MatrixDisplayBounds.IsEmpty == false)
                    sec.AddValue("MatrixDisplayBounds", MatrixDisplayBounds);
            }
            sec.AddValue("MatrixDisplayOrder", MatrixDisplayOrder, 0);
            sec.AddValue("MinContentSize", MinContentSize, new Size(100,100));
            if (_Titles != null && _Titles.Count > 0)
            {
                sec.AddStartElement("Titles count=\"" + _Titles.Count + "\"");
                foreach (ChartTitle title in _Titles)
                    sec.AddElement(title.GetSerialData(""));
                sec.AddEndElement("Titles");
            }
            if (_VScrollBar != null)
                sec.AddElement(_VScrollBar.GetSerialData("VScrollBar"));
            sec.AddValue("VScrollBarWidth", VScrollBarWidth, 9);
            sec.AddValue("VScrollBarVisible", VScrollBarVisible, true);
            sec.AddElement(base.GetSerialData(null));
            if (serialName != null)
                sec.AddEndElement("ChartContainer");
            return (sec);
        }
        #endregion
        #region PutSerialData
        #region ProcessValue
        internal override void ProcessValue(SerialElement se)
        {
            switch (se.Name)
            {
                case "AutoSizeMode":
                    AutoSizeMode = (AutoSizeMode)se.GetValueEnum(typeof(AutoSizeMode));
                    break;
                case "EmptyText":
                    EmptyText = se.StringValue;
                    break;
                case "EnableEmptyTextMarkup":
                    EnableEmptyTextMarkup = bool.Parse(se.StringValue);
                    break;
                case "EnablePanning":
                    EnablePanning = bool.Parse(se.StringValue);
                    break;
                case "EnableSelection":
                    EnableSelection = bool.Parse(se.StringValue);
                    break;
                case "FillWeight":
                    FillWeight = int.Parse(se.StringValue);
                    break;
                case "HScrollBarHeight":
                    HScrollBarHeight = int.Parse(se.StringValue);
                    break;
                case "HScrollBarVisible":
                    HScrollBarVisible = bool.Parse(se.StringValue);
                    break;
                case "MatrixAlignEndColumn":
                    MatrixAlignEndColumn = bool.Parse(se.StringValue);
                    break;
                case "MatrixAlignEndRow":
                    MatrixAlignEndRow = bool.Parse(se.StringValue);
                    break;
                case "MatrixAlignStartColumn":
                    MatrixAlignStartColumn = bool.Parse(se.StringValue);
                    break;
                case "MatrixAlignStartRow":
                    MatrixAlignStartRow = bool.Parse(se.StringValue);
                    break;
                case "MatrixDisplayBounds":
                    ChartPanel panel = Parent as ChartPanel;
                    if (panel == null || panel.AutoFillChartMatrix == false)
                        MatrixDisplayBounds = se.GetValueRect();
                    break;
                case "MatrixDisplayOrder":
                    MatrixDisplayOrder = int.Parse(se.StringValue);
                    break;
                case "MinContentSize":
                    MinContentSize = se.GetValueSize();
                    break;
                case "VScrollBarWidth":
                    VScrollBarWidth = int.Parse(se.StringValue);
                    break;
                case "VScrollBarVisible":
                    VScrollBarVisible = bool.Parse(se.StringValue);
                    break;
                default:
                    base.ProcessValue(se);
                    break;
            }
        }
        #endregion
        #region ProcessCollection
        internal override void ProcessCollection(SerialElement se)
        {
            SerialElementCollection sec = se.Sec;
            switch (se.Name)
            {
                case "ChartTitle":
                    string name = sec.GetItemValue("Name");
                    ChartTitle title = GetTitleByName(name);
                    if (title != null)
                        Titles.Remove(title);
                    title = new ChartTitle(name);
                    sec.PutSerialData(title);
                    Titles.Add(title);
                    break;
                case "ContainerVisualStyles":
                    sec.PutSerialData(ContainerVisualStyles);
                    break;
                case "HScrollBar":
                    sec.PutSerialData(HScrollBar);
                    break;
                case "Legend":
                    sec.PutSerialData(Legend);
                    break;
                case "Titles":
                    sec.PutSerialData(this);
                    break;
                case "VScrollBar":
                    sec.PutSerialData(VScrollBar);
                    break;
                default:
                    base.ProcessCollection(se);
                    break;
            }
        }
        #endregion
        #endregion
        #region States
        [Flags]
        private enum States : uint
        {
            AutoGenSeriesCollection = (1U << 0),
            EnableEmptyTextMarkup = (1U << 1),
            EnablePanning = (1U << 2),
            ShowPointsToolTips = (1U << 3),
            ShowSeriesToolTips = (1U << 4),
            HScrollBarEnabled = (1U << 5),
            VScrollBarEnabled = (1U << 6),
            HScrollBarVisible = (1U << 7),
            VScrollBarVisible = (1U << 8),
            LayoutBoundsValid = (1U << 9),
            IsSelected = (1U << 10),
            MatrixAlignStartColumn = (1U << 11),
            MatrixAlignEndColumn = (1U << 12),
            MatrixAlignStartRow = (1U << 13),
            MatrixAlignEndRow = (1U << 14),
            MatrixColumnAligned = (1U << 15),
            MatrixRowAligned = (1U << 16),
            EnableSelection = (1U << 17),
        }
        #region TestState
        private bool TestState(States state)
        {
            return ((_States & state) == state);
        }
        #endregion
        #region SetState
        private void SetState(States state, bool value)
        {
            if (value == true)
                _States |= state;
            else
                _States &= ~state;
        }
        #endregion
        #endregion
        #region IDisposable
        public override void Dispose()
        {
            ContainerVisualStyles = null;
            Titles = null;
            base.Dispose();
        }
        #endregion
    }
    #region enums
    #region AutoSizeMode
    /// 
    /// Defines auto-sizing mode.
    /// 
    public enum AutoSizeMode
    {
        /// 
        /// NotSet (None is default)
        /// 
        NotSet = -1,
        /// 
        /// No Auto-sizing will take place.
        /// 
        None,
        /// 
        /// Size will be determined by the fill weight.
        /// 
        Fill,
    }
    #endregion
    #endregion
}