File: Common\General\ChartArea.cs
Project: ndp\fx\src\DataVisualization\System.Windows.Forms.DataVisualization.csproj (System.Windows.Forms.DataVisualization)
//-------------------------------------------------------------
// <copyright company=’Microsoft Corporation’>
//   Copyright © Microsoft Corporation. All Rights Reserved.
// </copyright>
//-------------------------------------------------------------
// @owner=alexgor, deliant
//=================================================================
//  File:		ChartArea.cs
//
//  Namespace:	System.Web.UI.WebControls[Windows.Forms].Charting
//
//	Classes:	ChartArea
//
//  Purpose:	The ChartArea class represents one chart area within 
//              a chart image, and is used to plot one or more chart 
//              series. The number of chart series that can be plotted 
//              in a chart area is unlimited.
//
//	Reviewed:	GS - August 6, 2002
//				AG - August 7, 2002
//              AG - Microsoft 16, 2007
//
//===================================================================
 
#region Used namespaces
using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Data;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Globalization;
using System.Diagnostics.CodeAnalysis;
 
#if Microsoft_CONTROL

	using System.Windows.Forms.DataVisualization.Charting.Data;
	using System.Windows.Forms.DataVisualization.Charting.ChartTypes;
	using System.Windows.Forms.DataVisualization.Charting.Utilities;
	using System.Windows.Forms.DataVisualization.Charting.Borders3D;
	using System.Windows.Forms.DataVisualization.Charting;
	using System.ComponentModel.Design.Serialization;
	using System.Reflection;
	using System.Windows.Forms.Design;
#else
	using System.Web;
	using System.Web.UI;
	using System.Web.UI.DataVisualization.Charting;
	using System.Web.UI.DataVisualization.Charting.Data;
	using System.Web.UI.DataVisualization.Charting.ChartTypes;
	using System.Web.UI.DataVisualization.Charting.Utilities;
	using System.Web.UI.DataVisualization.Charting.Borders3D;
#endif
 
 
#endregion
 
#if Microsoft_CONTROL
	namespace System.Windows.Forms.DataVisualization.Charting
#else
namespace System.Web.UI.DataVisualization.Charting
#endif
{
	#region Chart area aligment enumerations
 
    /// <summary>
    /// An enumeration of the alignment orientations of a ChartArea
    /// </summary>
		[Flags]
		public enum AreaAlignmentOrientations
		{
			/// <summary>
            /// Chart areas are not automatically aligned.
			/// </summary>
			None = 0,
 
			/// <summary>
            /// Chart areas are aligned vertically.
			/// </summary>
			Vertical = 1,
 
			/// <summary>
            /// Chart areas are aligned horizontally.
			/// </summary>
			Horizontal = 2,
 
			/// <summary>
            /// Chart areas are aligned using all values (horizontally and vertically).
			/// </summary>
			All = Vertical | Horizontal
		}
 
        /// <summary>
        /// An enumeration of the alignment styles of a ChartArea
        /// </summary>
		[Flags]
		public enum AreaAlignmentStyles
		{
			/// <summary>
            /// Chart areas are not automatically aligned.
			/// </summary>
			None = 0,
 
			/// <summary>
            /// Chart areas are aligned by positions.
			/// </summary>
			Position = 1,
 
			/// <summary>
            /// Chart areas are aligned by inner plot positions.
			/// </summary>
			PlotPosition = 2,
 
            /// <summary>
            /// Chart areas are aligned by axes views.
            /// </summary>
            AxesView = 4,
 
#if Microsoft_CONTROL

			/// <summary>
			/// Cursor and Selection alignment.
			/// </summary>
			Cursor = 8,
 
			/// <summary>
			/// Complete alignment.
			/// </summary>
			All = Position | PlotPosition | Cursor | AxesView
#else // Microsoft_CONTROL
 
   			/// <summary>
			/// Complete alignment.
			/// </summary>
            All = Position | PlotPosition | AxesView
 
#endif // Microsoft_CONTROL
        }
 
	#endregion
 
	/// <summary>
	/// The ChartArea class is used to create and display a chart 
	/// area within a chart image. The chart area is a rectangular 
	/// area on a chart image.  It has 4 axes, horizontal and vertical grids. 
    /// A chart area can contain more than one different chart type.  
    /// The number of chart series that can be plotted in a chart area 
    /// is unlimited.
    /// 
    /// ChartArea class exposes all the properties and methods
    /// of its base ChartArea3D class.
	/// </summary>
		[
		DefaultProperty("Axes"),
		SRDescription("DescriptionAttributeChartArea_ChartArea"),
		]
#if ASPPERM_35
	[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
        [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
#endif
        public partial class ChartArea : ChartNamedElement
		{
		    #region Chart Area Fields
 
            /// <summary>
            /// Plot area position
            /// </summary>
            internal ElementPosition PlotAreaPosition;
 
			// Private data members, which store properties values
			private Axis[]					_axisArray = new Axis[4];
			private Color					_backColor = Color.Empty;
#if Microsoft_CONTROL
			private bool					_backColorIsSet = false;
#endif
			private ChartHatchStyle			_backHatchStyle = ChartHatchStyle.None;
			private string					_backImage = "";
			private ChartImageWrapMode		_backImageWrapMode = ChartImageWrapMode.Tile;
			private Color					_backImageTransparentColor = Color.Empty;
			private ChartImageAlignmentStyle			_backImageAlignment = ChartImageAlignmentStyle.TopLeft;
			private GradientStyle			_backGradientStyle = GradientStyle.None;
			private Color					_backSecondaryColor = Color.Empty;
			private Color					_borderColor = Color.Black;
			private int						_borderWidth = 1;
			private ChartDashStyle			_borderDashStyle = ChartDashStyle.NotSet;
			private int						_shadowOffset = 0;
			private Color					_shadowColor = Color.FromArgb(128, 0, 0, 0);
			private ElementPosition			_areaPosition = null;
			private ElementPosition			_innerPlotPosition = null;
			internal int					IterationCounter = 0;
 
			private		bool				_isSameFontSizeForAllAxes = false;
			internal	float				axesAutoFontSize = 8f;
 
            private string                      _alignWithChartArea = Constants.NotSetValue;
			private		AreaAlignmentOrientations	_alignmentOrientation = AreaAlignmentOrientations.Vertical;
			private		AreaAlignmentStyles			_alignmentStyle = AreaAlignmentStyles.All;
			private		int						_circularSectorNumber = int.MinValue;
			private		int						_circularUsePolygons = int.MinValue;
 
			// Flag indicates that chart area is acurrently aligned
			internal	bool					alignmentInProcess = false;
 
			// Chart area position before adjustments
			internal	RectangleF				originalAreaPosition = RectangleF.Empty;
 
			// Chart area inner plot position before adjustments
			internal	RectangleF				originalInnerPlotPosition = RectangleF.Empty;
 
            // Chart area position before adjustments
            internal    RectangleF              lastAreaPosition = RectangleF.Empty;
 
 
			// Center of the circulat chart area
			internal	PointF					circularCenter = PointF.Empty;
 
			private		ArrayList				_circularAxisList = null;
 
#if Microsoft_CONTROL
			// Buffered plotting area image
			internal		Bitmap				areaBufferBitmap = null;
 
            private	Cursor                      _cursorX = new Cursor();
            private Cursor                      _cursorY = new Cursor();
#endif
 
            // Area SmartLabel class
			internal		SmartLabel			smartLabels = new SmartLabel();
 
			// Gets or sets a flag that specifies whether the chart area is visible.
			private			bool				_visible = true;
 
		#endregion
 
		    #region Chart Area Cursor properties
 
#if Microsoft_CONTROL

			/// <summary>
			/// Gets or sets a Cursor object that is used for cursors and selected ranges along the X-axis.
			/// </summary>
			[
			SRCategory("CategoryAttributeCursor"),
			Bindable(true),
			DefaultValue(null),
			SRDescription("DescriptionAttributeChartArea_CursorX"),
			DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
			TypeConverter(typeof(NoNameExpandableObjectConverter)),
			]
			public Cursor CursorX
			{
				get
				{
					return _cursorX;
				}
				set
				{
					_cursorX = value;
 
					// Initialize chart object
					_cursorX.Initialize(this, AxisName.X);
				}
			}
 
			/// <summary>
			/// Gets or sets a Cursor object that is used for cursors and selected ranges along the Y-axis.
			/// </summary>
			[
			SRCategory("CategoryAttributeCursor"),
			Bindable(true),
			DefaultValue(null),
			SRDescription("DescriptionAttributeChartArea_CursorY"),
			DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
			TypeConverter(typeof(NoNameExpandableObjectConverter)),
			]
			public Cursor CursorY
			{
				get
				{
					return _cursorY;
				}
				set
				{
					_cursorY = value;
 
					// Initialize chart object
					_cursorY.Initialize(this, AxisName.Y);
				}
			}
 
#endif // Microsoft_CONTROL
 
            #endregion
 
            #region Chart Area properties
 
			/// <summary>
			/// Gets or sets a flag that specifies whether the chart area is visible.
			/// </summary>
			/// <remarks>
			/// When this flag is set to false, all series, legends, titles and annotation objects 
			/// associated with the chart area will also be hidden.
			/// </remarks>
			/// <value>
			/// <b>True</b> if the chart area is visible; <b>false</b> otherwise.
			/// </value>
			[
			SRCategory("CategoryAttributeAppearance"),
			DefaultValue(true),
			SRDescription("DescriptionAttributeChartArea_Visible"),
			ParenthesizePropertyNameAttribute(true),
			]
			virtual public bool Visible
			{
				get
				{
					return _visible;
				}
				set
				{
					_visible = value;
					this.Invalidate();
				}
			}
 
			/// <summary>
            /// Gets or sets the name of the ChartArea object to which this chart area should be aligned.
			/// </summary>
			[
			SRCategory("CategoryAttributeAlignment"),
			Bindable(true),
            DefaultValue(Constants.NotSetValue),
			SRDescription("DescriptionAttributeChartArea_AlignWithChartArea"),
			TypeConverter(typeof(LegendAreaNameConverter)),
		#if !Microsoft_CONTROL
		PersistenceMode(PersistenceMode.Attribute)
		#endif
			]
			public string AlignWithChartArea
			{
				get
				{
					return _alignWithChartArea;
				}
				set
				{
                    if (value != _alignWithChartArea)
                    {
                        if (String.IsNullOrEmpty(value))
                        {
                            _alignWithChartArea = Constants.NotSetValue;
                        }
                        else
                        {
                            if (Chart != null && Chart.ChartAreas != null)
                            {
                                Chart.ChartAreas.VerifyNameReference(value);
                            }
                            _alignWithChartArea = value;
                        }
                        Invalidate();
                    }
				}
			}
 
			/// <summary>
            /// Gets or sets the alignment orientation of a chart area.
			/// </summary>
			[
            SRCategory("CategoryAttributeAlignment"),
			Bindable(true),
			DefaultValue(AreaAlignmentOrientations.Vertical),
			SRDescription("DescriptionAttributeChartArea_AlignOrientation"),
            Editor(Editors.FlagsEnumUITypeEditor.Editor, Editors.FlagsEnumUITypeEditor.Base),
		    #if !Microsoft_CONTROL
		    PersistenceMode(PersistenceMode.Attribute)
		    #endif
			]
			public AreaAlignmentOrientations	AlignmentOrientation
			{
				get
				{
					return _alignmentOrientation;
				}
				set
				{
					_alignmentOrientation = value;
					Invalidate();
				}
			}
 
 
			/// <summary>
			/// Gets or sets the alignment style of the ChartArea.
			/// </summary>
			[
            SRCategory("CategoryAttributeAlignment"),
			Bindable(true),
			DefaultValue(AreaAlignmentStyles.All),
			SRDescription("DescriptionAttributeChartArea_AlignType"),
            Editor(Editors.FlagsEnumUITypeEditor.Editor, Editors.FlagsEnumUITypeEditor.Base),
		#if !Microsoft_CONTROL
		PersistenceMode(PersistenceMode.Attribute)
		#endif
			]
			public AreaAlignmentStyles AlignmentStyle
			{
				get
				{
					return _alignmentStyle;
				}
				set
				{
					_alignmentStyle = value;
					Invalidate();
				}
			}
 
			/// <summary>
            /// Gets or sets an array that represents all axes for a chart area.
			/// </summary>
			[
			SRCategory("CategoryAttributeAxes"),
			Bindable(true),
			SRDescription("DescriptionAttributeChartArea_Axes"),
			TypeConverter(typeof(AxesArrayConverter)),
            Editor(Editors.AxesArrayEditor.Editor, Editors.AxesArrayEditor.Base),
			DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
			SerializationVisibilityAttribute(SerializationVisibility.Hidden)
			]
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
			public Axis[] Axes
			{
				get
				{
					return _axisArray;
				}
				set
				{
					AxisX = value[0];
					AxisY = value[1];
					AxisX2 = value[2];
					AxisY2 = value[3];
					Invalidate();
				}
			}
 
			/// <summary>
			/// Avoid serialization of the axes array
			/// </summary>
            [EditorBrowsableAttribute(EditorBrowsableState.Never)]
			internal bool ShouldSerializeAxes()
			{
				return false;
			}
 
			/// <summary>
            /// Gets or sets an Axis object that represents the primary Y-axis. 
			/// </summary>
			[
			SRCategory("CategoryAttributeAxis"),
			Bindable(true),
			Browsable(false),
			SRDescription("DescriptionAttributeChartArea_AxisY"),
#if Microsoft_CONTROL
			DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
#else
		PersistenceMode(PersistenceMode.InnerProperty),
#endif
			TypeConverter(typeof(NoNameExpandableObjectConverter))
			]
			public Axis AxisY
			{
				get
				{
					return axisY;
				}
				set
				{
					axisY = value;
					axisY.Initialize(this, AxisName.Y);
					_axisArray[1] = axisY;
					Invalidate();
				}
			}
 
			/// <summary>
            /// Gets or sets an Axis object that represents the primary X-axis. 
			/// </summary>
			[
			SRCategory("CategoryAttributeAxis"),
			Bindable(true),
			Browsable(false),
			SRDescription("DescriptionAttributeChartArea_AxisX"),
#if Microsoft_CONTROL
			DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
#else
		PersistenceMode(PersistenceMode.InnerProperty),
#endif
			TypeConverter(typeof(NoNameExpandableObjectConverter))
			]
			public Axis AxisX
			{
				get
				{
					return axisX;
				}
				set
				{
					axisX = value;
					axisX.Initialize(this, AxisName.X);
					_axisArray[0] = axisX;
					Invalidate();
				}
			}
 
			/// <summary>
            /// Gets or sets an Axis object that represents the secondary X-axis. 
			/// </summary>
			[
			SRCategory("CategoryAttributeAxis"),
			Bindable(true),
			Browsable(false),
			SRDescription("DescriptionAttributeChartArea_AxisX2"),
#if Microsoft_CONTROL
			DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
#else
		PersistenceMode(PersistenceMode.InnerProperty),
#endif
			TypeConverter(typeof(NoNameExpandableObjectConverter))
			]
			public Axis AxisX2
			{
				get
				{
					return axisX2;
				}
				set
				{
					axisX2 = value;
					axisX2.Initialize(this, AxisName.X2);
					_axisArray[2] = axisX2;
					Invalidate();
				}
			}
 
			/// <summary>
            /// Gets or sets an Axis object that represents the secondary Y-axis.
			/// </summary>
			[
			SRCategory("CategoryAttributeAxis"),
			Bindable(true),
			Browsable(false),
			SRDescription("DescriptionAttributeChartArea_AxisY2"),
#if Microsoft_CONTROL
			DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
#else
		PersistenceMode(PersistenceMode.InnerProperty),
#endif
			TypeConverter(typeof(NoNameExpandableObjectConverter))
			]
			public Axis AxisY2
			{
				get
				{
					return axisY2;
				}
				set
				{
					axisY2 = value;
					axisY2.Initialize(this, AxisName.Y2);
					_axisArray[3] = axisY2;
					Invalidate();
				}
			}
 
			/// <summary>
            /// Gets or sets an ElementPosition object, which defines the position of a chart area object within the chart image.
			/// </summary>
			[
			SRCategory("CategoryAttributeAppearance"),
			Bindable(true),
			SRDescription("DescriptionAttributeChartArea_Position"),
#if Microsoft_CONTROL
			DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
#else
		    PersistenceMode(PersistenceMode.InnerProperty),
#endif
			NotifyParentPropertyAttribute(true),
			TypeConverter(typeof(ElementPositionConverter)),
			SerializationVisibilityAttribute(SerializationVisibility.Element)
			]
			public ElementPosition Position
			{
				get
				{	
					// Serialize only position values if Auto set to false
					if(this.Chart != null && this.Chart.serializationStatus == SerializationStatus.Saving )
					{
						if(_areaPosition.Auto)
						{
							return new ElementPosition();	
						}
						else
						{
							ElementPosition newPosition = new ElementPosition();
#if Microsoft_CONTROL
							newPosition.Auto = false;
#else
						newPosition.Auto = true;
#endif
							newPosition.SetPositionNoAuto(_areaPosition.X, _areaPosition.Y, _areaPosition.Width, _areaPosition.Height);
							return newPosition;
						}
					}
					return _areaPosition;
				}
				set
				{
					_areaPosition = value;
					_areaPosition.Parent = this;
					_areaPosition.resetAreaAutoPosition = true;
					Invalidate();
				}
			}
 
            /// <summary>
            /// Determoines if this position should be serialized.
            /// </summary>
            /// <returns></returns>
            internal bool ShouldSerializePosition()
            {
                return !this.Position.Auto;
            }
 
			/// <summary>
            /// Gets or sets an ElementPosition object, which defines the inner plot position of a chart area object.  
			/// </summary>
			[
			SRCategory("CategoryAttributeAppearance"),
			Bindable(true),
			SRDescription("DescriptionAttributeChartArea_InnerPlotPosition"),
#if Microsoft_CONTROL
			DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
#else
		    PersistenceMode(PersistenceMode.InnerProperty),
#endif
			NotifyParentPropertyAttribute(true),
			TypeConverter(typeof(ElementPositionConverter)),
			SerializationVisibilityAttribute(SerializationVisibility.Element)
			]
			public ElementPosition InnerPlotPosition
			{
				get
				{	
					// Serialize only position values if Auto set to false
                    if (this.Common != null && this.Common.Chart != null && this.Common.Chart.serializationStatus == SerializationStatus.Saving)
					{
						if(_innerPlotPosition.Auto)
						{
							return new ElementPosition();	
						}
						else
						{
							ElementPosition newPosition = new ElementPosition();
#if Microsoft_CONTROL
							newPosition.Auto = false;
#else
						newPosition.Auto = true;
#endif
							newPosition.SetPositionNoAuto(_innerPlotPosition.X, _innerPlotPosition.Y, _innerPlotPosition.Width, _innerPlotPosition.Height);
							return newPosition;
						}
					}
					return _innerPlotPosition;
				}
				set
				{
					_innerPlotPosition = value;
					_innerPlotPosition.Parent = this;
					Invalidate();
				}
			}
 
            /// <summary>
            /// Determoines if this position should be serialized.
            /// </summary>
            /// <returns></returns>
            internal bool ShouldSerializeInnerPlotPosition()
            {
                return !this.InnerPlotPosition.Auto;
            }
 
			/// <summary>
            /// Gets or sets the background color of a ChartArea object. 
			/// </summary>
			[
 
			SRCategory("CategoryAttributeAppearance"),
			Bindable(true),
			DefaultValue(typeof(Color), ""),
            SRDescription("DescriptionAttributeBackColor"),
			NotifyParentPropertyAttribute(true),
            TypeConverter(typeof(ColorConverter)),
            Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
		#if !Microsoft_CONTROL
		PersistenceMode(PersistenceMode.Attribute)
		#endif
			]
			public Color BackColor
			{
				get
				{
#if Microsoft_CONTROL
					if (SystemInformation.HighContrast && AccessibilityImprovements.Level3 &&
					_backColor.IsEmpty && !_backColorIsSet)
					{
						return SystemColors.Control;
					}
#endif
 
					return _backColor;
				}
				set
				{
					_backColor = value;
#if Microsoft_CONTROL
					_backColorIsSet = true;
#endif
				Invalidate();
				}
			}
 
			/// <summary>
            /// Gets or sets the hatching style of a ChartArea object.
			/// </summary>
			[
 
 
			SRCategory("CategoryAttributeAppearance"),
			Bindable(true),
			DefaultValue(ChartHatchStyle.None),
			NotifyParentPropertyAttribute(true),
            SRDescription("DescriptionAttributeBackHatchStyle"),
#if !Microsoft_CONTROL
		PersistenceMode(PersistenceMode.Attribute),
#endif
            Editor(Editors.HatchStyleEditor.Editor, Editors.HatchStyleEditor.Base)
 
			]
			public ChartHatchStyle BackHatchStyle
			{
				get
				{
					return _backHatchStyle;
				}
				set
				{
					_backHatchStyle = value;
					Invalidate();
				}
			}
 
			/// <summary>
            /// Gets or sets the background image of a ChartArea object. 
			/// </summary>
			[
			SRCategory("CategoryAttributeAppearance"),
			Bindable(true),
			DefaultValue(""),
            SRDescription("DescriptionAttributeBackImage"),
            Editor(Editors.ImageValueEditor.Editor, Editors.ImageValueEditor.Base),
#if !Microsoft_CONTROL
		PersistenceMode(PersistenceMode.Attribute),
#endif
			NotifyParentPropertyAttribute(true)
			]
			public string BackImage
			{
				get
				{
					return _backImage;
				}
				set
				{
					_backImage = value;
					Invalidate();
				}
			}
 
			/// <summary>
            /// Gets or sets the drawing mode of the background image of a ChartArea object.
			/// </summary>
			[
			SRCategory("CategoryAttributeAppearance"),
			Bindable(true),
			DefaultValue(ChartImageWrapMode.Tile),
			NotifyParentPropertyAttribute(true),
            SRDescription("DescriptionAttributeImageWrapMode"),
#if !Microsoft_CONTROL
		PersistenceMode(PersistenceMode.Attribute)
#endif
			]
			public ChartImageWrapMode BackImageWrapMode
			{
				get
				{
					return _backImageWrapMode;
				}
				set
				{
					_backImageWrapMode = value;
					Invalidate();
				}
			}
 
			/// <summary>
            /// Gets or sets the color of a ChartArea object's background image that will be drawn as transparent.  
			/// </summary>
			[
			SRCategory("CategoryAttributeAppearance"),
			Bindable(true),
			DefaultValue(typeof(Color), ""),
			NotifyParentPropertyAttribute(true),
            SRDescription("DescriptionAttributeImageTransparentColor"),
            TypeConverter(typeof(ColorConverter)),
            Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
#if !Microsoft_CONTROL
		PersistenceMode(PersistenceMode.Attribute)
#endif
			]
			public Color BackImageTransparentColor
			{
				get
				{
					return _backImageTransparentColor;
				}
				set
				{
					_backImageTransparentColor = value;
					Invalidate();
				}
			}
 
			/// <summary>
            /// Gets or sets the alignment of a ChartArea object. 
			/// </summary>
			[
			SRCategory("CategoryAttributeAppearance"),
			Bindable(true),
			DefaultValue(ChartImageAlignmentStyle.TopLeft),
			NotifyParentPropertyAttribute(true),
            SRDescription("DescriptionAttributeBackImageAlign"),
#if !Microsoft_CONTROL
		PersistenceMode(PersistenceMode.Attribute)
#endif
			]
			public ChartImageAlignmentStyle BackImageAlignment
			{
				get
				{
					return _backImageAlignment;
				}
				set
				{
					_backImageAlignment = value;
					Invalidate();
				}
			}
 
			/// <summary>
            /// Gets or sets the orientation of a chart element's gradient, 
            /// and also determines whether or not a gradient is used.  
			/// </summary>
			[
 
            SRCategory("CategoryAttributeAppearance"),
			Bindable(true),
			DefaultValue(GradientStyle.None),
			NotifyParentPropertyAttribute(true),
            SRDescription("DescriptionAttributeBackGradientStyle"),
#if !Microsoft_CONTROL
		PersistenceMode(PersistenceMode.Attribute),
#endif
            Editor(Editors.GradientEditor.Editor, Editors.GradientEditor.Base)
			]		
			public GradientStyle BackGradientStyle
			{
				get
				{
					return _backGradientStyle;
				}
				set
				{
					_backGradientStyle = value;
					Invalidate();
				}
			}
 
			/// <summary>
            /// Gets or sets the secondary color of a ChartArea object.
			/// </summary>
			[
 
            SRCategory("CategoryAttributeAppearance"),
			Bindable(true),
			DefaultValue(typeof(Color), ""),
			NotifyParentPropertyAttribute(true),
            SRDescription("DescriptionAttributeBackSecondaryColor"),
            TypeConverter(typeof(ColorConverter)),
            Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
#if !Microsoft_CONTROL
		PersistenceMode(PersistenceMode.Attribute)
#endif
			] 
			public Color BackSecondaryColor
			{
				get
				{
					return _backSecondaryColor;
				}
				set
				{
					_backSecondaryColor = value;
					Invalidate();
				}
			}
 
			/// <summary>
            /// Gets or sets the shadow color of a ChartArea object.  
			/// </summary>
			[
			SRCategory("CategoryAttributeAppearance"),
			Bindable(true),
			DefaultValue(typeof(Color), "128,0,0,0"),
            SRDescription("DescriptionAttributeShadowColor"),
			NotifyParentPropertyAttribute(true),
            TypeConverter(typeof(ColorConverter)),
            Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
#if !Microsoft_CONTROL
		PersistenceMode(PersistenceMode.Attribute)
#endif
			]
			public Color ShadowColor
			{
				get
				{
					return _shadowColor;
				}
				set
				{
					_shadowColor = value;
					Invalidate();
				}
			}
 
			/// <summary>
            /// Gets or sets the shadow offset (in pixels) of a ChartArea object.
			/// </summary>
			[
			SRCategory("CategoryAttributeAppearance"),
			Bindable(true),
			DefaultValue(0),
            SRDescription("DescriptionAttributeShadowOffset"),
			NotifyParentPropertyAttribute(true),
#if !Microsoft_CONTROL
		PersistenceMode(PersistenceMode.Attribute)
#endif
			]
			public int ShadowOffset
			{
				get
				{
					return _shadowOffset;
				}
				set
				{
					_shadowOffset = value;
					Invalidate();
				}
			}
 
			/// <summary>
            /// Gets or sets the border color of a ChartArea object.
			/// </summary>
			[
 
            SRCategory("CategoryAttributeAppearance"),
			Bindable(true),
			DefaultValue(typeof(Color), "Black"),
            SRDescription("DescriptionAttributeBorderColor"),
			NotifyParentPropertyAttribute(true),
            TypeConverter(typeof(ColorConverter)),
            Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
#if !Microsoft_CONTROL
		PersistenceMode(PersistenceMode.Attribute)
#endif
			]
			public Color BorderColor
			{
				get
				{
					return _borderColor;
				}
				set
				{
					_borderColor = value;
					Invalidate();
				}
			}
 
			/// <summary>
            /// Gets or sets the border width of a ChartArea object.
			/// </summary>
			[
 
			SRCategory("CategoryAttributeAppearance"),
			Bindable(true),
			DefaultValue(1),
            SRDescription("DescriptionAttributeBorderWidth"),
			NotifyParentPropertyAttribute(true),
#if !Microsoft_CONTROL
		PersistenceMode(PersistenceMode.Attribute)
#endif
			]
			public int BorderWidth
			{
				get
				{
					return _borderWidth;
				}
				set
				{
					if(value < 0)
					{
                        throw (new ArgumentOutOfRangeException("value", SR.ExceptionBorderWidthIsNegative));
					}
					_borderWidth = value;
					Invalidate();
				}
			}
 
			/// <summary>
            /// Gets or sets the style of the border line of a ChartArea object.
			/// </summary>
			[
 
            SRCategory("CategoryAttributeAppearance"),
			Bindable(true),
			DefaultValue(ChartDashStyle.NotSet),
            SRDescription("DescriptionAttributeBorderDashStyle"),
			NotifyParentPropertyAttribute(true),
#if !Microsoft_CONTROL
		PersistenceMode(PersistenceMode.Attribute)
#endif
			]
			public ChartDashStyle BorderDashStyle
			{
				get
				{
					return _borderDashStyle;
				}
				set
				{
					_borderDashStyle = value;
					Invalidate();
				}
			}
 
			/// <summary>
            /// Gets or sets the unique name of a ChartArea object.
			/// </summary>
			[
 
			SRCategory("CategoryAttributeMisc"),
			Bindable(true),
			SRDescription("DescriptionAttributeChartArea_Name"),
			NotifyParentPropertyAttribute(true),
#if !Microsoft_CONTROL
		PersistenceMode(PersistenceMode.Attribute)
#endif
			]
			public override string Name
			{
				get
				{
					return base.Name;
				}
				set
				{
                    base.Name = value;
				}
			}
 
            /// <summary>
            /// Gets or sets a Boolean that determines if the labels of the axes for all chart area
            /// , which have LabelsAutoFit property set to true, are of equal size.  
            /// </summary>
			[
			SRCategory("CategoryAttributeAppearance"),
			Bindable(true),
			DefaultValue(false),
			SRDescription("DescriptionAttributeChartArea_EquallySizedAxesFont"),
			NotifyParentPropertyAttribute(true),
#if !Microsoft_CONTROL
		PersistenceMode(PersistenceMode.Attribute)
#endif
			]
			public bool IsSameFontSizeForAllAxes
			{
				get
				{
					return _isSameFontSizeForAllAxes;
				}
				set
				{
					_isSameFontSizeForAllAxes = value;
					Invalidate();
				}
			}
 
 
#endregion
 
#region Constructors
            /// <summary>
			/// ChartArea constructor.
			/// </summary>
			public ChartArea()
			{
				Initialize();
			}
 
            /// <summary>
            /// ChartArea constructor.
            /// </summary>
            /// <param name="name">The name.</param>
            public ChartArea(string name) : base(name)
            {
                Initialize();
            }
#endregion
 
#region Chart Area Methods
			/// <summary>
			/// Restores series order and X axis reversed mode for the 3D charts.
			/// </summary>
			internal void Restore3DAnglesAndReverseMode()
			{
				if(this.Area3DStyle.Enable3D && !this.chartAreaIsCurcular)
				{
					// Restore axis "IsReversed" property and old Y angle
					this.AxisX.IsReversed = oldReverseX;
					this.AxisX2.IsReversed = oldReverseX;
					this.AxisY.IsReversed = oldReverseY;
					this.AxisY2.IsReversed = oldReverseY;
					this.Area3DStyle.Rotation = oldYAngle;
				}
			}
	
			/// <summary>
			/// Sets series order and X axis reversed mode for the 3D charts.
			/// </summary>
			internal void Set3DAnglesAndReverseMode()
			{
				// Clear series reversed flag
				_reverseSeriesOrder = false;
 
				// If 3D charting is enabled
				if(this.Area3DStyle.Enable3D)
				{
					// Make sure primary & secondary axis has the same IsReversed settings
					// This is a limitation for the 3D chart required for labels drawing.
					this.AxisX2.IsReversed = this.AxisX.IsReversed;
					this.AxisY2.IsReversed = this.AxisY.IsReversed;
 
					// Remember reversed order of X & Y axis and Angles
					oldReverseX = this.AxisX.IsReversed;
					oldReverseY = this.AxisY.IsReversed;
					oldYAngle = this.Area3DStyle.Rotation;
 
					// Check if Y angle 
					if(this.Area3DStyle.Rotation > 90 || this.Area3DStyle.Rotation < -90)
					{
                        // This method depends on the 'switchValueAxes' field which is calculated based on the chart types
                        // of the series associated with the chart area. We need to call SetData method to make sure this field
                        // is correctly initialized. Because we only need to collect information about the series, we pass 'false'
                        // as parameters to limit the amount of work this function does.
                        this.SetData(false, false);
 
						// Reversed series order
						_reverseSeriesOrder = true;
 
						// Reversed primary and secondary X axis
						if(!this.switchValueAxes)
						{
							this.AxisX.IsReversed = !this.AxisX.IsReversed;
							this.AxisX2.IsReversed = !this.AxisX2.IsReversed;
						}
 
							// Reversed primary and secondary Y axis for chart types like Bar
						else
						{
							this.AxisY.IsReversed = !this.AxisY.IsReversed;
							this.AxisY2.IsReversed = !this.AxisY2.IsReversed;
						}
 
						// Adjust Y angle
						if(this.Area3DStyle.Rotation > 90)
						{
							this.Area3DStyle.Rotation = (this.Area3DStyle.Rotation - 90) - 90;
						}
						else if(this.Area3DStyle.Rotation < -90)
						{
							this.Area3DStyle.Rotation = (this.Area3DStyle.Rotation + 90) + 90;
						}
					}
				}
			}
 
			/// <summary>
			/// Save all automatic values like Minimum and Maximum.
			/// </summary>
			internal void SetTempValues()
			{
				// Save non automatic area position
				if(!this.Position.Auto)
				{
					this.originalAreaPosition = this.Position.ToRectangleF();
				}
 
				// Save non automatic area inner plot position
				if(!this.InnerPlotPosition.Auto)
				{
					this.originalInnerPlotPosition = this.InnerPlotPosition.ToRectangleF();
				}
			
				this._circularSectorNumber = int.MinValue;
				this._circularUsePolygons = int.MinValue;
				this._circularAxisList = null;
 
				// Save Minimum and maximum values for all axes
				axisX.StoreAxisValues();
				axisX2.StoreAxisValues();
				axisY.StoreAxisValues();
				axisY2.StoreAxisValues();
			}
 
			/// <summary>
			/// Load all automatic values like Minimum and Maximum with original values.
			/// </summary>
			internal void GetTempValues()
			{
				// Take Minimum and maximum values for all axes
				axisX.ResetAxisValues();
				axisX2.ResetAxisValues();
				axisY.ResetAxisValues();
				axisY2.ResetAxisValues();
 
				// Restore non automatic area position
				if(!this.originalAreaPosition.IsEmpty)
				{
                    this.lastAreaPosition = this.Position.ToRectangleF();
                    this.Position.SetPositionNoAuto(this.originalAreaPosition.X, this.originalAreaPosition.Y, this.originalAreaPosition.Width, this.originalAreaPosition.Height);
					this.originalAreaPosition = RectangleF.Empty;
				}
 
				// Save non automatic area inner plot position
				if(!this.originalInnerPlotPosition.IsEmpty)
				{
                    this.InnerPlotPosition.SetPositionNoAuto(this.originalInnerPlotPosition.X, this.originalInnerPlotPosition.Y, this.originalInnerPlotPosition.Width, this.originalInnerPlotPosition.Height);
					this.originalInnerPlotPosition = RectangleF.Empty;
				}
			}
		
			/// <summary>
			/// Initialize Chart area and axes
			/// </summary>
			internal void Initialize()
			{
                // Initialize 3D style class
                _area3DStyle = new ChartArea3DStyle(this);
 
				// Create axes for this chart area.
				axisY = new Axis( );
				axisX = new Axis( );
				axisX2 = new Axis( );
				axisY2 = new Axis( );
 
				// Initialize axes;
				axisX.Initialize(this, AxisName.X);
				axisY.Initialize(this, AxisName.Y);
				axisX2.Initialize(this, AxisName.X2);
				axisY2.Initialize(this, AxisName.Y2);
 
				// Initialize axes array
				_axisArray[0] = axisX;
				_axisArray[1] = axisY;
				_axisArray[2] = axisX2;
				_axisArray[3] = axisY2;
 
				// Set flag to reset auto values for all areas
                _areaPosition = new ElementPosition(this);
				_areaPosition.resetAreaAutoPosition = true;
 
                _innerPlotPosition = new ElementPosition(this);
			
				// Set the position of the new chart area
				if( PlotAreaPosition == null )
				{
					PlotAreaPosition = new ElementPosition(this);
				}
	
#if Microsoft_CONTROL

				// Initialize cursor class
                this._cursorX.Initialize(this, AxisName.X);
                this._cursorY.Initialize(this, AxisName.Y);
 
#endif // Microsoft_CONTROL
			}
 
			/// <summary>
			/// Minimum and maximum do not have to be calculated 
			/// from data series every time. It is very time 
			/// consuming. Minimum and maximum are buffered 
			/// and only when this flags are set Minimum and 
			/// Maximum are refreshed from data.
			/// </summary>
			internal void ResetMinMaxFromData()
			{
				_axisArray[0].refreshMinMaxFromData = true;
				_axisArray[1].refreshMinMaxFromData = true;
				_axisArray[2].refreshMinMaxFromData = true;
				_axisArray[3].refreshMinMaxFromData = true;
			}
 
 			/// <summary>
			/// Recalculates the axes scale of a chart area.
			/// </summary>
			public void RecalculateAxesScale()
			{
				// Read axis Max/Min from data
				ResetMinMaxFromData();
 
#if Microsoft_CONTROL
				Set3DAnglesAndReverseMode();
				SetTempValues();
#endif
 
				// Initialize area position
				_axisArray[0].ReCalc( PlotAreaPosition );
				_axisArray[1].ReCalc( PlotAreaPosition );
				_axisArray[2].ReCalc( PlotAreaPosition );
				_axisArray[3].ReCalc( PlotAreaPosition );
			
				// Find all Data and chart types which belong 
				// to this chart area an set default values
				SetData();
 
#if Microsoft_CONTROL
				Restore3DAnglesAndReverseMode();
				GetTempValues();
#endif
			}
 
			/// <summary>
			/// RecalculateAxesScale the chart area
			/// </summary>
			internal void ReCalcInternal()
			{
				// Initialize area position
				_axisArray[0].ReCalc( PlotAreaPosition );
				_axisArray[1].ReCalc( PlotAreaPosition );
				_axisArray[2].ReCalc( PlotAreaPosition );
				_axisArray[3].ReCalc( PlotAreaPosition );
			
				// Find all Data and chart types which belong 
				// to this chart area an set default values
				SetData();
			}
 
 
			/// <summary>
			/// Reset auto calculated chart area values.
			/// </summary>
			internal void ResetAutoValues()
			{
				_axisArray[0].ResetAutoValues();
				_axisArray[1].ResetAutoValues();
				_axisArray[2].ResetAutoValues();
				_axisArray[3].ResetAutoValues();
			}
 
			/// <summary>
			/// Calculates Position for the background.
			/// </summary>
			/// <param name="withScrollBars">Calculate with scroll bars</param>
			/// <returns>Background rectangle</returns>
			internal RectangleF GetBackgroundPosition( bool withScrollBars )
			{
				// For pie and doughnut, which do not have axes, the position 
				// for the background is Chart area position not plotting 
				// area position.
				RectangleF backgroundPosition = PlotAreaPosition.ToRectangleF();
				if( !requireAxes )
				{
					backgroundPosition = Position.ToRectangleF();
				}
 
                // Without scroll bars
				if( !withScrollBars )
				{
					return backgroundPosition;
				}
 
				// Add scroll bar rectangles to the area background 
				RectangleF backgroundPositionWithScrollBars = new RectangleF(backgroundPosition.Location, backgroundPosition.Size);
 
#if Microsoft_CONTROL

				if( requireAxes )
				{
					// Loop through all axis
					foreach(Axis axis in this.Axes)
					{
						// Find axis with visible scroll bars
						if(axis.ScrollBar.IsVisible && axis.ScrollBar.IsPositionedInside)
						{
							// Change size of the background rectangle depending on the axis position
							if(axis.AxisPosition == AxisPosition.Bottom)
							{
								backgroundPositionWithScrollBars.Height += (float)axis.ScrollBar.GetScrollBarRelativeSize();
							}
							else if(axis.AxisPosition == AxisPosition.Top)
							{
								backgroundPositionWithScrollBars.Y -= (float)axis.ScrollBar.GetScrollBarRelativeSize();
								backgroundPositionWithScrollBars.Height += (float)axis.ScrollBar.GetScrollBarRelativeSize();
							}
							else if(axis.AxisPosition == AxisPosition.Left)
							{
								backgroundPositionWithScrollBars.X -= (float)axis.ScrollBar.GetScrollBarRelativeSize();
								backgroundPositionWithScrollBars.Width += (float)axis.ScrollBar.GetScrollBarRelativeSize();
							}
							else if(axis.AxisPosition == AxisPosition.Left)
							{
								backgroundPositionWithScrollBars.Width += (float)axis.ScrollBar.GetScrollBarRelativeSize();
							}
						}
					}
				}
 
#endif // Microsoft_CONTROL
				return backgroundPositionWithScrollBars;
			}
 
			/// <summary>
			/// Call when the chart area is resized.
			/// </summary>
			/// <param name="chartGraph">Chart graphics object.</param>
			internal void Resize(ChartGraphics chartGraph)
			{
				// Initialize plotting area position
				RectangleF plottingRect = Position.ToRectangleF();
				if(!InnerPlotPosition.Auto)
				{
					plottingRect.X += (Position.Width / 100F) * InnerPlotPosition.X;
					plottingRect.Y += (Position.Height / 100F) * InnerPlotPosition.Y;
					plottingRect.Width = (Position.Width / 100F) * InnerPlotPosition.Width;
					plottingRect.Height = (Position.Height / 100F) * InnerPlotPosition.Height;
				}
 
				//******************************************************
				//** Calculate number of vertical and horizontal axis
				//******************************************************
				int	verticalAxes = 0;
				int	horizontalAxes = 0;
				foreach(Axis axis in this.Axes)
				{
					if(axis.enabled)
					{
						if(axis.AxisPosition == AxisPosition.Bottom)
						{
							++horizontalAxes;		
						}
						else if(axis.AxisPosition == AxisPosition.Top)
						{
							++horizontalAxes;
						}
						else if(axis.AxisPosition == AxisPosition.Left)
						{
							++verticalAxes;
						}
						else if(axis.AxisPosition == AxisPosition.Right)
						{
							++verticalAxes;
						}
					}
				}
				if(horizontalAxes <= 0 )
				{
					horizontalAxes = 1;
				}
				if(verticalAxes <= 0 )
				{
					verticalAxes = 1;
				}
 
 
				//******************************************************
				//** Find same auto-fit font size
				//******************************************************
				Axis[] axisArray = (this.switchValueAxes) ? 
					new Axis[] {this.AxisX, this.AxisX2, this.AxisY, this.AxisY2} :
					new Axis[] {this.AxisY, this.AxisY2, this.AxisX, this.AxisX2};
				if(this.IsSameFontSizeForAllAxes)
				{
					axesAutoFontSize = 20;
					foreach(Axis axis in axisArray)
					{
						// Process only enabled axis
						if(axis.enabled)
						{
							// Resize axis
							if(axis.AxisPosition == AxisPosition.Bottom || axis.AxisPosition == AxisPosition.Top)
							{
								axis.Resize(chartGraph, this.PlotAreaPosition, plottingRect, horizontalAxes, InnerPlotPosition.Auto);
							}
							else
							{
								axis.Resize(chartGraph, this.PlotAreaPosition, plottingRect, verticalAxes, InnerPlotPosition.Auto);
							}
 
							// Calculate smallest font size
							if(axis.IsLabelAutoFit && axis.autoLabelFont != null)
							{
								axesAutoFontSize = Math.Min(axesAutoFontSize, axis.autoLabelFont.Size);
							}
						}
					}
				}
 
				//******************************************************
				//** Adjust plotting area position according to the axes 
				//** elements (title, labels, tick marks) size.
				//******************************************************
				RectangleF	rectLabelSideSpacing = RectangleF.Empty;
				foreach(Axis axis in axisArray)
				{
					// Process only enabled axis
					if( ! axis.enabled )
					{
						//******************************************************
						//** Adjust for the 3D Wall Width for disabled axis
						//******************************************************
						if(InnerPlotPosition.Auto && this.Area3DStyle.Enable3D && !this.chartAreaIsCurcular)
						{
							SizeF areaWallSize = chartGraph.GetRelativeSize(new SizeF(this.Area3DStyle.WallWidth, this.Area3DStyle.WallWidth));
							if(axis.AxisPosition == AxisPosition.Bottom)
							{
								plottingRect.Height -= areaWallSize.Height;
							}
							else if(axis.AxisPosition == AxisPosition.Top)
							{
								plottingRect.Y += areaWallSize.Height;
								plottingRect.Height -= areaWallSize.Height;
							}
							else if(axis.AxisPosition == AxisPosition.Right)
							{
								plottingRect.Width -= areaWallSize.Width;
							}
							else if(axis.AxisPosition == AxisPosition.Left)
							{
								plottingRect.X += areaWallSize.Width;
								plottingRect.Width -= areaWallSize.Width;
							}
						}
 
						continue;
					}
 
					//******************************************************
					//** Calculate axes elements position
					//******************************************************
					if(axis.AxisPosition == AxisPosition.Bottom || axis.AxisPosition == AxisPosition.Top)
					{
						axis.Resize(chartGraph, this.PlotAreaPosition, plottingRect, horizontalAxes, InnerPlotPosition.Auto);
					}
					else
					{
						axis.Resize(chartGraph, this.PlotAreaPosition, plottingRect, verticalAxes, InnerPlotPosition.Auto);
					}
 
					// Shift top/bottom labels so they will not overlap with left/right labels
					PreventTopBottomAxesLabelsOverlapping(axis);
 
					//******************************************************
					//** Check axis position
					//******************************************************
					float axisPosition = (float)axis.GetAxisPosition();
					if(axis.AxisPosition == AxisPosition.Bottom)
					{
						if(!axis.GetIsMarksNextToAxis())
						{
							axisPosition = plottingRect.Bottom;
						}
						axisPosition = plottingRect.Bottom - axisPosition;
					}
					else if(axis.AxisPosition == AxisPosition.Top)
					{
						if(!axis.GetIsMarksNextToAxis())
						{
							axisPosition = plottingRect.Y;
						}
						axisPosition = axisPosition - plottingRect.Top;
					}
					else if(axis.AxisPosition == AxisPosition.Right)
					{
						if(!axis.GetIsMarksNextToAxis())
						{
							axisPosition = plottingRect.Right;
						}
						axisPosition = plottingRect.Right - axisPosition;
					}
					else if(axis.AxisPosition == AxisPosition.Left)
					{
						if(!axis.GetIsMarksNextToAxis())
						{
							axisPosition = plottingRect.X;
						}
						axisPosition = axisPosition - plottingRect.Left;
					}
 
					//******************************************************
					//** Adjust axis elements size with axis position
					//******************************************************
					// Calculate total size of axis elements
					float axisSize = axis.markSize + axis.labelSize;
 
#if SUBAXES
					// Add sub-axis size
					if(!this.chartAreaIsCurcular && !this.Area3DStyle.Enable3D)
					{
						foreach(SubAxis subAxis in axis.SubAxes)
						{
							axisSize += subAxis.markSize + subAxis.labelSize + subAxis.titleSize;
						}
					}
#endif // SUBAXES
 
                    // Adjust depending on the axis position
					axisSize -= axisPosition;
					if(axisSize < 0)
					{
						axisSize = 0;
					}
 
 
					// Add axis title and scroll bar size (always outside of plotting area)
					axisSize += axis.titleSize + axis.scrollBarSize;
 
 
					// Calculate horizontal axes size for circualar area
					if(this.chartAreaIsCurcular && 
						(axis.AxisPosition == AxisPosition.Top || axis.AxisPosition == AxisPosition.Bottom) )
					{
						axisSize = axis.titleSize + axis.markSize + axis.scrollBarSize;
					}
 
					//******************************************************
					//** Adjust plotting area
					//******************************************************
					if(InnerPlotPosition.Auto)
					{
						if(axis.AxisPosition == AxisPosition.Bottom)
						{
							plottingRect.Height -= axisSize;
						}
						else if(axis.AxisPosition == AxisPosition.Top)
						{
							plottingRect.Y += axisSize;
							plottingRect.Height -= axisSize;
						}
						else if(axis.AxisPosition == AxisPosition.Left)
						{
							plottingRect.X += axisSize;
							plottingRect.Width -= axisSize;
						}
						else if(axis.AxisPosition == AxisPosition.Right)
						{
							plottingRect.Width -= axisSize;
						}
 
                        // Check if labels side offset should be processed
                        bool addLabelsSideOffsets = true;
 
						// Update the plotting area depending on the size required for labels on the sides
                        if (addLabelsSideOffsets)
                        {
                            if (axis.AxisPosition == AxisPosition.Bottom || axis.AxisPosition == AxisPosition.Top)
                            {
                                if (axis.labelNearOffset != 0 && axis.labelNearOffset < Position.X)
                                {
                                    float offset = Position.X - axis.labelNearOffset;
                                    if (Math.Abs(offset) > plottingRect.Width * 0.3f)
                                    {
                                        offset = plottingRect.Width * 0.3f;
                                    }
 
                                    // NOTE: Code was removed to solve an issue with extra space when labels angle = 45
                                    //rectLabelSideSpacing.Width = (float)Math.Max(offset, rectLabelSideSpacing.Width);
                                    rectLabelSideSpacing.X = (float)Math.Max(offset, rectLabelSideSpacing.X);
                                }
 
                                if (axis.labelFarOffset > Position.Right)
                                {
                                    if ((axis.labelFarOffset - Position.Right) < plottingRect.Width * 0.3f)
                                    {
                                        rectLabelSideSpacing.Width = (float)Math.Max(axis.labelFarOffset - Position.Right, rectLabelSideSpacing.Width);
                                    }
                                    else
                                    {
                                        rectLabelSideSpacing.Width = (float)Math.Max(plottingRect.Width * 0.3f, rectLabelSideSpacing.Width);
                                    }
                                }
                            }
 
                            else
                            {
                                if (axis.labelNearOffset != 0 && axis.labelNearOffset < Position.Y)
                                {
                                    float offset = Position.Y - axis.labelNearOffset;
                                    if (Math.Abs(offset) > plottingRect.Height * 0.3f)
                                    {
                                        offset = plottingRect.Height * 0.3f;
                                    }
 
                                    // NOTE: Code was removed to solve an issue with extra space when labels angle = 45
                                    //rectLabelSideSpacing.Height = (float)Math.Max(offset, rectLabelSideSpacing.Height);
                                    rectLabelSideSpacing.Y = (float)Math.Max(offset, rectLabelSideSpacing.Y);
                                }
 
                                if (axis.labelFarOffset > Position.Bottom)
                                {
                                    if ((axis.labelFarOffset - Position.Bottom) < plottingRect.Height * 0.3f)
                                    {
                                        rectLabelSideSpacing.Height = (float)Math.Max(axis.labelFarOffset - Position.Bottom, rectLabelSideSpacing.Height);
                                    }
                                    else
                                    {
                                        rectLabelSideSpacing.Height = (float)Math.Max(plottingRect.Height * 0.3f, rectLabelSideSpacing.Height);
                                    }
                                }
                            }
                        }
					}
				}
 
				//******************************************************
				//** Make sure there is enough space 
				//** for labels on the chart sides
				//******************************************************
                if (!this.chartAreaIsCurcular)
                {
                    if (rectLabelSideSpacing.Y > 0 && rectLabelSideSpacing.Y > plottingRect.Y - Position.Y)
                    {
                        float delta = (plottingRect.Y - Position.Y) - rectLabelSideSpacing.Y;
                        plottingRect.Y -= delta;
                        plottingRect.Height += delta;
                    }
                    if (rectLabelSideSpacing.X > 0 && rectLabelSideSpacing.X > plottingRect.X - Position.X)
                    {
                        float delta = (plottingRect.X - Position.X) - rectLabelSideSpacing.X;
                        plottingRect.X -= delta;
                        plottingRect.Width += delta;
                    }
                    if (rectLabelSideSpacing.Height > 0 && rectLabelSideSpacing.Height > Position.Bottom - plottingRect.Bottom)
                    {
                        plottingRect.Height += (Position.Bottom - plottingRect.Bottom) - rectLabelSideSpacing.Height;
                    }
                    if (rectLabelSideSpacing.Width > 0 && rectLabelSideSpacing.Width > Position.Right - plottingRect.Right)
                    {
                        plottingRect.Width += (Position.Right - plottingRect.Right) - rectLabelSideSpacing.Width;
                    }
                }
 
				//******************************************************
				//** Plotting area must be square for the circular 
				//** chart area (in pixels).
				//******************************************************
				if(this.chartAreaIsCurcular)
				{
					// Adjust area to fit the axis title
					float	xTitleSize = (float)Math.Max(this.AxisY.titleSize, this.AxisY2.titleSize);
					if(xTitleSize > 0)
					{
						plottingRect.X += xTitleSize;
						plottingRect.Width -= 2f * xTitleSize;
					}
					float	yTitleSize = (float)Math.Max(this.AxisX.titleSize, this.AxisX2.titleSize);
					if(yTitleSize > 0)
					{
						plottingRect.Y += yTitleSize;
						plottingRect.Height -= 2f * yTitleSize;
					}
 
					// Make a square plotting rect
					RectangleF rect = chartGraph.GetAbsoluteRectangle( plottingRect );
					if(rect.Width > rect.Height)
					{
						rect.X += (rect.Width - rect.Height) / 2f;
						rect.Width = rect.Height;
					}
					else
					{
						rect.Y += (rect.Height - rect.Width) / 2f;
						rect.Height = rect.Width;					
					}
					plottingRect = chartGraph.GetRelativeRectangle( rect );
 
					// Remember circular chart area center
					this.circularCenter = new PointF(plottingRect.X + plottingRect.Width/2f, plottingRect.Y + plottingRect.Height/2f);
 
					// Calculate auto-fit font of the circular axis labels and update area position
					FitCircularLabels(chartGraph, this.PlotAreaPosition, ref plottingRect, xTitleSize, yTitleSize);
				}
 
				//******************************************************
				//** Set plotting area position
				//******************************************************
				if(plottingRect.Width < 0f)
				{
					plottingRect.Width = 0f;
				}
				if(plottingRect.Height < 0f)
				{
					plottingRect.Height = 0f;
				}
				PlotAreaPosition.FromRectangleF(plottingRect);
				InnerPlotPosition.SetPositionNoAuto(
					(float)Math.Round((plottingRect.X - Position.X) / (Position.Width / 100F), 5), 
					(float)Math.Round((plottingRect.Y - Position.Y) / (Position.Height / 100F), 5), 
					(float)Math.Round(plottingRect.Width / (Position.Width / 100F), 5), 
					(float)Math.Round(plottingRect.Height / (Position.Height / 100F), 5));
 
 
				//******************************************************
				//** Adjust label font size for axis, which were 
				//** automatically calculated after the opposite axis 
				//** change the size of plotting area.
				//******************************************************
				this.AxisY2.AdjustLabelFontAtSecondPass(chartGraph, InnerPlotPosition.Auto);
				this.AxisY.AdjustLabelFontAtSecondPass(chartGraph, InnerPlotPosition.Auto);
				if(InnerPlotPosition.Auto)
				{
					this.AxisX2.AdjustLabelFontAtSecondPass(chartGraph, InnerPlotPosition.Auto);
					this.AxisX.AdjustLabelFontAtSecondPass(chartGraph, InnerPlotPosition.Auto);
				}
 
			}
 
            /// <summary>
            /// Finds axis by it's position. Can be Null.
            /// </summary>
            /// <param name="axisPosition">Axis position to find</param>
            /// <returns>Found axis.</returns>
			private Axis FindAxis(AxisPosition axisPosition)
			{
				foreach(Axis axis in this.Axes)
				{
					if(axis.AxisPosition == axisPosition)
					{
						return axis;
					}
				}
				return null;
			}
 
			/// <summary>
			/// Shift top/bottom labels so they will not overlap with left/right labels.
			/// </summary>
			/// <param name="axis">Axis to shift up/down.</param>
			private void PreventTopBottomAxesLabelsOverlapping(Axis axis)
			{
				// If axis is not on the edge of the chart area do not
				// try to adjust it's position when axis labels overlap
				// labels of the oppositie axis.
				if( !axis.IsAxisOnAreaEdge )
				{
					return;
				}
 
				// Shift bottom axis labels down
				if(axis.AxisPosition == AxisPosition.Bottom)
				{
					// Get labels position
					float labelsPosition = (float)axis.GetAxisPosition();
					if( !axis.GetIsMarksNextToAxis() )
					{
						labelsPosition = axis.PlotAreaPosition.Bottom;
					}
 
					// Only adjust labels outside plotting area
					if(Math.Round(labelsPosition, 2) < Math.Round(axis.PlotAreaPosition.Bottom, 2))
					{
						return;
					}
 
					// Check if labels may overlap with Left axis
					Axis	leftAxis = FindAxis(AxisPosition.Left);
					if(leftAxis != null && 
                        leftAxis.enabled &&
						leftAxis.labelFarOffset != 0 &&
						leftAxis.labelFarOffset > labelsPosition &&
						axis.labelNearOffset != 0 && 
						axis.labelNearOffset < PlotAreaPosition.X)
					{
						float overlap = (float)(leftAxis.labelFarOffset - labelsPosition) * 0.75f;
						if(overlap > axis.markSize)
						{
							axis.markSize += overlap - axis.markSize;
						}
					}
 
					// Check if labels may overlap with Right axis
					Axis	rightAxis = FindAxis(AxisPosition.Right);
					if(rightAxis != null &&
                        rightAxis.enabled &&
						rightAxis.labelFarOffset != 0 &&
						rightAxis.labelFarOffset > labelsPosition &&
						axis.labelFarOffset != 0 && 
						axis.labelFarOffset > PlotAreaPosition.Right)
					{
						float overlap = (float)(rightAxis.labelFarOffset - labelsPosition) * 0.75f;
						if(overlap > axis.markSize)
						{
							axis.markSize += overlap - axis.markSize;
						}
					}
				}
 
					// Shift top axis labels up
				else if(axis.AxisPosition == AxisPosition.Top)
				{
					// Get labels position
					float labelsPosition = (float)axis.GetAxisPosition();
					if( !axis.GetIsMarksNextToAxis() )
					{
						labelsPosition = axis.PlotAreaPosition.Y;
					}
 
					// Only adjust labels outside plotting area
					if(Math.Round(labelsPosition, 2) < Math.Round(axis.PlotAreaPosition.Y, 2))
					{
						return;
					}
 
					// Check if labels may overlap with Left axis
					Axis	leftAxis = FindAxis(AxisPosition.Left);
					if(leftAxis != null &&
                        leftAxis.enabled &&
						leftAxis.labelNearOffset != 0 &&
						leftAxis.labelNearOffset < labelsPosition &&
						axis.labelNearOffset != 0 && 
						axis.labelNearOffset < PlotAreaPosition.X)
					{
						float overlap = (float)(labelsPosition - leftAxis.labelNearOffset) * 0.75f;
						if(overlap > axis.markSize)
						{
							axis.markSize += overlap - axis.markSize;
						}
					}
 
					// Check if labels may overlap with Right axis
					Axis	rightAxis = FindAxis(AxisPosition.Right);
					if(rightAxis != null &&
                        rightAxis.enabled &&
						rightAxis.labelNearOffset != 0 &&
						rightAxis.labelNearOffset < labelsPosition &&
						axis.labelFarOffset != 0 && 
						axis.labelFarOffset > PlotAreaPosition.Right)
					{
						float overlap = (float)(labelsPosition - rightAxis.labelNearOffset) * 0.75f;
						if(overlap > axis.markSize)
						{
							axis.markSize += overlap - axis.markSize;
						}
					}
				}
 
			}
 
#endregion
 
#region Painting and Selection Methods
 
			/// <summary>
			/// Draws chart area background and/or border.
			/// </summary>
			/// <param name="graph">Chart graphics.</param>
			/// <param name="position">Background position.</param>
			/// <param name="borderOnly">Draws chart area border only.</param>
			private void PaintAreaBack(ChartGraphics graph, RectangleF position, bool borderOnly)
			{
				if(!borderOnly)
				{
					// Draw background
					if(!this.Area3DStyle.Enable3D || !requireAxes || chartAreaIsCurcular)
					{
						// 3D Pie Chart doesn't need scene
						// Draw 2D background
						graph.FillRectangleRel( 
							position, 
							BackColor, 
							BackHatchStyle, 
							BackImage, 
							BackImageWrapMode, 				
							BackImageTransparentColor,
							BackImageAlignment,
							BackGradientStyle, 
							BackSecondaryColor, 
							(requireAxes) ? Color.Empty : BorderColor, 
							(requireAxes) ? 0 : BorderWidth, 
							BorderDashStyle, 
							ShadowColor, 
							ShadowOffset, 
							PenAlignment.Outset,
							chartAreaIsCurcular,
							(chartAreaIsCurcular && this.CircularUsePolygons) ? this.CircularSectorsNumber : 0,
							this.Area3DStyle.Enable3D);
					}
					else
					{
						// Draw chart area 3D scene
						this.DrawArea3DScene(graph, position);
					}
				}
				else
				{
					if(!this.Area3DStyle.Enable3D || !requireAxes || chartAreaIsCurcular)
					{
						// Draw chart area border
						if(BorderColor != Color.Empty && BorderWidth > 0)
						{
							graph.FillRectangleRel( position, 
								Color.Transparent, 
								ChartHatchStyle.None, 
								"", 
								ChartImageWrapMode.Tile, 				
								Color.Empty,
								ChartImageAlignmentStyle.Center,
								GradientStyle.None, 
								Color.Empty, 
								BorderColor, 
								BorderWidth, 
								BorderDashStyle, 
								Color.Empty, 
								0, 
								PenAlignment.Outset,
								chartAreaIsCurcular,
								(chartAreaIsCurcular && this.CircularUsePolygons) ? this.CircularSectorsNumber : 0,
								this.Area3DStyle.Enable3D);
						}
					}
 
				}
			}
 
			/// <summary>
			/// Paint the chart area.
			/// </summary>
			/// <param name="graph">Chart graphics.</param>
			internal void Paint( ChartGraphics graph )
			{
                    // Check if plot area position was recalculated.
                    // If not and non-auto InnerPlotPosition & Position were
                    // specified - do all needed calculations
                    if (PlotAreaPosition.Width == 0 &&
                        PlotAreaPosition.Height == 0 &&
                        !InnerPlotPosition.Auto
                        && !Position.Auto)
                    {
                        // Initialize plotting area position
                        RectangleF plottingRect = Position.ToRectangleF();
                        if (!InnerPlotPosition.Auto)
                        {
                            plottingRect.X += (Position.Width / 100F) * InnerPlotPosition.X;
                            plottingRect.Y += (Position.Height / 100F) * InnerPlotPosition.Y;
                            plottingRect.Width = (Position.Width / 100F) * InnerPlotPosition.Width;
                            plottingRect.Height = (Position.Height / 100F) * InnerPlotPosition.Height;
                        }
 
                        PlotAreaPosition.FromRectangleF(plottingRect);
                    }
 
                    // Get background position rectangle.
                    RectangleF backgroundPositionWithScrollBars = GetBackgroundPosition(true);
                    RectangleF backgroundPosition = GetBackgroundPosition(false);
 
                    // Add hot region for plotting area.
                    if (Common.ProcessModeRegions)
                    {
                        Common.HotRegionsList.AddHotRegion(backgroundPosition, this, ChartElementType.PlottingArea, true);
                    }
                    // Draw background
                    PaintAreaBack(graph, backgroundPositionWithScrollBars, false);
 
                    // Call BackPaint event
                    Common.Chart.CallOnPrePaint(new ChartPaintEventArgs(this, graph, Common, PlotAreaPosition));
 
                    // Draw chart types without axes - Pie.
                    if (!requireAxes && ChartTypes.Count != 0)
                    {
                        // Find first chart type that do not require axis (like Pie) and draw it.
                        // Chart types that do not require axes (circular charts) cannot be combined with
                        // any other chart types.
                        // NOTE: Fixes issues #4672 and #4692
                        for (int chartTypeIndex = 0; chartTypeIndex < ChartTypes.Count; chartTypeIndex++)
                        {
                            IChartType chartType = Common.ChartTypeRegistry.GetChartType((string)ChartTypes[chartTypeIndex]);
                            if (!chartType.RequireAxes)
                            {
                                chartType.Paint(graph, Common, this, null);
                                break;
                            }
                        }
 
                        // Call Paint event
                        Common.Chart.CallOnPostPaint(new ChartPaintEventArgs(this, graph, Common, PlotAreaPosition));
                        return;
                    }
 
 
 
                    // Reset Smart Labels 
                    this.smartLabels.Reset();
 
 
 
                    // Set values for optimized drawing
                    foreach (Axis currentAxis in this._axisArray)
                    {
                        currentAxis.optimizedGetPosition = true;
                        currentAxis.paintViewMax = currentAxis.ViewMaximum;
                        currentAxis.paintViewMin = currentAxis.ViewMinimum;
                        currentAxis.paintRange = currentAxis.paintViewMax - currentAxis.paintViewMin;
                        currentAxis.paintAreaPosition = PlotAreaPosition.ToRectangleF();
                        if (currentAxis.ChartArea != null && currentAxis.ChartArea.chartAreaIsCurcular)
                        {
                            // Update position for circular chart area
                            currentAxis.paintAreaPosition.Width /= 2.0f;
                            currentAxis.paintAreaPosition.Height /= 2.0f;
                        }
                        currentAxis.paintAreaPositionBottom = currentAxis.paintAreaPosition.Y + currentAxis.paintAreaPosition.Height;
                        currentAxis.paintAreaPositionRight = currentAxis.paintAreaPosition.X + currentAxis.paintAreaPosition.Width;
                        if (currentAxis.AxisPosition == AxisPosition.Top || currentAxis.AxisPosition == AxisPosition.Bottom)
                            currentAxis.paintChartAreaSize = currentAxis.paintAreaPosition.Width;
                        else
                            currentAxis.paintChartAreaSize = currentAxis.paintAreaPosition.Height;
 
                        currentAxis.valueMultiplier = 0.0;
                        if (currentAxis.paintRange != 0)
                        {
                            currentAxis.valueMultiplier = currentAxis.paintChartAreaSize / currentAxis.paintRange;
                        }
                    }
                    
                    // Draw Axis Striplines (only when StripWidth > 0)
                    bool useScaleSegments = false;
                    Axis[] axesArray = new Axis[] { axisY, axisY2, axisX, axisX2 };
                    foreach (Axis currentAxis in axesArray)
                    {
 
                        useScaleSegments = (currentAxis.ScaleSegments.Count > 0);
 
                        if (!useScaleSegments)
                        {
                            currentAxis.PaintStrips(graph, false);
                        }
 
                        else
                        {
                            foreach (AxisScaleSegment scaleSegment in currentAxis.ScaleSegments)
                            {
                                scaleSegment.SetTempAxisScaleAndInterval();
 
                                currentAxis.PaintStrips(graph, false);
 
                                scaleSegment.RestoreAxisScaleAndInterval();
                            }
                        }
					}
 
                    // Draw Axis Grids
                    axesArray = new Axis[] { axisY, axisX2, axisY2, axisX };
                    foreach (Axis currentAxis in axesArray)
                    {
 
                        useScaleSegments = (currentAxis.ScaleSegments.Count > 0);
 
                        if (!useScaleSegments)
                        {
                            currentAxis.PaintGrids(graph);
                        }
 
                        else
                        {
                            foreach (AxisScaleSegment scaleSegment in currentAxis.ScaleSegments)
                            {
                                scaleSegment.SetTempAxisScaleAndInterval();
 
                                currentAxis.PaintGrids(graph);
 
                                scaleSegment.RestoreAxisScaleAndInterval();
                            }
                        }
 
                    }
 
                    // Draw Axis Striplines (only when StripWidth == 0)
                    foreach (Axis currentAxis in axesArray)
                    {
 
                        useScaleSegments = (currentAxis.ScaleSegments.Count > 0);
 
                        if (!useScaleSegments)
                        {
                            currentAxis.PaintStrips(graph, true);
                        }
 
                        else
                        {
                            foreach (AxisScaleSegment scaleSegment in currentAxis.ScaleSegments)
                            {
                                scaleSegment.SetTempAxisScaleAndInterval();
 
                                currentAxis.PaintStrips(graph, true);
 
                                scaleSegment.RestoreAxisScaleAndInterval();
                            }
                        }
 
                    }
 
                    // Draw Axis elements on the back of the 3D scene
                    if (this.Area3DStyle.Enable3D && !this.chartAreaIsCurcular)
                    {
                        foreach (Axis currentAxis in axesArray)
                        {
 
                            useScaleSegments = (currentAxis.ScaleSegments.Count > 0);
 
                            if (!useScaleSegments)
                            {
                                currentAxis.PrePaint(graph);
                            }
 
                            else
                            {
                                foreach (AxisScaleSegment scaleSegment in currentAxis.ScaleSegments)
                                {
                                    scaleSegment.SetTempAxisScaleAndInterval();
 
                                    currentAxis.PrePaint(graph);
 
                                    scaleSegment.RestoreAxisScaleAndInterval();
                                }
 
                            }
 
                        }
                    }
 
                    // Draws chart area border
                    bool borderDrawn = false;
                    if (this.Area3DStyle.Enable3D || !IsBorderOnTopSeries())
                    {
                        borderDrawn = true;
                        PaintAreaBack(graph, backgroundPosition, true);
                    }
 
                    // Draw chart types
                    if (!this.Area3DStyle.Enable3D || this.chartAreaIsCurcular)
                    {
                        // Drawing in 2D space
 
                        // NOTE: Fixes issue #6443 and #5385
                        // If two chart series of the same type (for example Line) are separated
                        // by other series (for example Area) the order is not correct.
                        // Old implementation draws ALL series that belongs to the chart type.
                        ArrayList typeAndSeries = this.GetChartTypesAndSeriesToDraw(); 
                        
                        // Draw series by chart type or by series
                        foreach (ChartTypeAndSeriesInfo chartTypeInfo in typeAndSeries)
                        {
                            this.IterationCounter = 0;
                            IChartType type = Common.ChartTypeRegistry.GetChartType(chartTypeInfo.ChartType);
 
                            // If 'chartTypeInfo.Series' set to NULL all series of that chart type are drawn at once
                            type.Paint(graph, Common, this, chartTypeInfo.Series);
                        }
                    }
                    else
                    {
                        // Drawing in 3D space
                        PaintChartSeries3D(graph);
                    }
 
                    // Draw area border if it wasn't drawn prior to the series
                    if (!borderDrawn)
                    {
                        PaintAreaBack(graph, backgroundPosition, true);
                    }
 
                    // Draw Axis
                    foreach (Axis currentAxis in axesArray)
                    {
 
                        useScaleSegments = (currentAxis.ScaleSegments.Count > 0);
 
                        if (!useScaleSegments)
                        {
                            // Paint axis and Reset temp axis offset for side-by-side charts like column
                            currentAxis.Paint(graph);
                        }
 
                        else
                        {
                            // Some of the axis elements like grid lines and tickmarks 
                            // are drawn for each segment
                            foreach (AxisScaleSegment scaleSegment in currentAxis.ScaleSegments)
                            {
                                scaleSegment.SetTempAxisScaleAndInterval();
 
                                currentAxis.PaintOnSegmentedScalePassOne(graph);
 
                                scaleSegment.RestoreAxisScaleAndInterval();
                            }
 
                            // Other elements like labels, title, axis line are drawn once
                            currentAxis.PaintOnSegmentedScalePassTwo(graph);
                        }
 
                    }
 
                    // Call Paint event
                    Common.Chart.CallOnPostPaint(new ChartPaintEventArgs(this, graph, Common, PlotAreaPosition));
 
                    // Draw axis scale break lines
                    axesArray = new Axis[] { axisY, axisY2 };
                    foreach (Axis currentAxis in axesArray)
                    {
                        for (int segmentIndex = 0; segmentIndex < (currentAxis.ScaleSegments.Count - 1); segmentIndex++)
                        {
                            currentAxis.ScaleSegments[segmentIndex].PaintBreakLine(graph, currentAxis.ScaleSegments[segmentIndex + 1]);
 
                        }
                    }
 
                    // Reset values for optimized drawing
                    foreach (Axis curentAxis in this._axisArray)
                    {
                        curentAxis.optimizedGetPosition = false;
 
 
                        // Reset preffered number of intervals on the axis
                        curentAxis.prefferedNumberofIntervals = 5;
 
                        // Reset flag that scale segments are used
                        curentAxis.scaleSegmentsUsed = false;
 
 
                    }
		}
 
		/// <summary>
		/// Checks if chart area border should be drawn on top of series.
		/// </summary>
		/// <returns>True if border should be darwn on top.</returns>
		private bool IsBorderOnTopSeries()
		{
			// For most of the chart types chart area border is drawn on top.
			bool result = true;
			foreach( Series series in this.Common.Chart.Series )
			{
				if(series.ChartArea == this.Name)
				{
					// It is common for the Bubble and Point chart types to draw markers
					// partially outside of the chart area. By drawing the border before
					// series we avoiding the possibility of drawing the border line on 
					// top of the marker.
					if(series.ChartType == SeriesChartType.Bubble || 
						series.ChartType == SeriesChartType.Point)
					{
						return false;
					}
				}
			}
			return result;
		}
 
		/// <summary>
		/// Paint the chart area cursors.
		/// </summary>
		/// <param name="graph">Chart graphics.</param>
		/// <param name="cursorOnly">Indicates that only cursors are redrawn.</param>
        [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", Justification = "These parameters are used when compiling for the Microsoft version of Chart")]
		internal void PaintCursors( ChartGraphics graph, bool cursorOnly )
		{
			// Cursors and selection are supoorted only in 2D charts
			if(this.Area3DStyle.Enable3D == true)
			{
				return;
			}
 
			// Do not draw cursor/selection for chart types that do not require axis (like Pie)
			if(!this.requireAxes)
			{
				return;
			}
 
			// Cursors and selection are not supoorted in circular areas
			if(this.chartAreaIsCurcular)
			{
				return;
			}
 
			// Do not draw cursor/selection while printing
			if(this.Common != null && 
				this.Common.ChartPicture != null && 
				this.Common.ChartPicture.isPrinting)
			{
				return;
			}
 
			// Do not draw cursor/selection when chart area is not visible
			// because either width or height is set to zero
			if(this.Position.Width == 0f ||
				this.Position.Height == 0f)
			{
				return;
            }
 
#if Microsoft_CONTROL

            Chart chart = this.Common.Chart;
            ChartPicture chartPicture = Common.ChartPicture;
 
			// Check if cursor should be drawn
			if(!double.IsNaN(_cursorX.SelectionStart) ||
				!double.IsNaN(_cursorX.SelectionEnd) ||
				!double.IsNaN(_cursorX.Position) ||
				!double.IsNaN(_cursorY.SelectionStart) ||
				!double.IsNaN(_cursorY.SelectionEnd) ||
				!double.IsNaN(_cursorY.Position))
			{
 
				if(!chartPicture.backgroundRestored &&
					!chartPicture.isSelectionMode )
				{
					chartPicture.backgroundRestored = true;
 
					Rectangle chartPosition = new Rectangle(0, 0, chartPicture.Width, chartPicture.Height);
 
					// Get chart area position
					Rectangle absAreaPlotPosition = Rectangle.Round(graph.GetAbsoluteRectangle(PlotAreaPosition.ToRectangleF()));
					int maxCursorWidth = (CursorY.LineWidth > CursorX.LineWidth) ? CursorY.LineWidth + 1 : CursorX.LineWidth + 1;
					absAreaPlotPosition.Inflate(maxCursorWidth, maxCursorWidth);
					absAreaPlotPosition.Intersect(new Rectangle(0, 0, chart.Width, chart.Height));
 
					// Create area buffer bitmap
					if(areaBufferBitmap == null || 
						chartPicture.nonTopLevelChartBuffer == null ||
						!cursorOnly)
					{
						// Dispose previous bitmap
						if(areaBufferBitmap != null)
						{
							areaBufferBitmap.Dispose();
							areaBufferBitmap = null;
						}
						if(chartPicture.nonTopLevelChartBuffer != null)
						{
							chartPicture.nonTopLevelChartBuffer.Dispose();
							chartPicture.nonTopLevelChartBuffer = null;
						}
 
 
						// Copy chart area plotting rectangle from the chart's dubble buffer image into area dubble buffer image
						if(chart.paintBufferBitmap != null)
						{
							areaBufferBitmap = chart.paintBufferBitmap.Clone(absAreaPlotPosition, chart.paintBufferBitmap.PixelFormat);
						}
 
						// Copy whole chart from the chart's dubble buffer image into area dubble buffer image
						if(chart.paintBufferBitmap != null && 
							chart.paintBufferBitmap.Size.Width >= chartPosition.Size.Width &&
							chart.paintBufferBitmap.Size.Height >= chartPosition.Size.Height)
						{
							chartPicture.nonTopLevelChartBuffer = chart.paintBufferBitmap.Clone(
								chartPosition, chart.paintBufferBitmap.PixelFormat);
						}
 
					}
					else if(cursorOnly && chartPicture.nonTopLevelChartBuffer != null)
					{
						// Restore previous background
						chart.paintBufferBitmapGraphics.DrawImageUnscaled(
							chartPicture.nonTopLevelChartBuffer,
							chartPosition);
					}
				}
 
                // Draw chart area cursors and range selection
 
				_cursorY.Paint(graph);
				_cursorX.Paint(graph);
 
            }
#endif // Microsoft_CONTROL
 
        }
 
#endregion
 
#region Circular chart area methods
 
        /// <summary>
        /// Gets a circular chart type interface that belongs to this chart area.
        /// </summary>
        /// <returns>ICircularChartType interface or null.</returns>
		internal ICircularChartType GetCircularChartType()
		{
			// Get number of sectors in circular chart area
			foreach(Series series in this.Common.DataManager.Series)
			{
				if(series.IsVisible() && series.ChartArea == this.Name)
				{
					ICircularChartType type = Common.ChartTypeRegistry.GetChartType(series.ChartTypeName) as ICircularChartType;;
					if(type != null)
					{
						return type;
					}
				}
			}
			return null;
		}
 
		/// <summary>
		/// Calculate size of the circular axis labels and sets auto-fit font.
		/// </summary>
		/// <param name="chartGraph">Chart graphics object.</param>
		/// <param name="chartAreaPosition">The Chart area position.</param>
		/// <param name="plotArea">Plotting area size.</param>
		/// <param name="xTitleSize">Size of title on the axis.</param>
		/// <param name="yTitleSize">Size of title on the axis.</param>
		internal void FitCircularLabels(
			ChartGraphics chartGraph, 
			ElementPosition chartAreaPosition, 
			ref RectangleF plotArea,
			float xTitleSize,
			float yTitleSize)
		{
			// Check if axis labels are enabled
			if(!this.AxisX.LabelStyle.Enabled)
			{
				return;
			}
 
			// Get absolute titles size
			SizeF	titleSize = chartGraph.GetAbsoluteSize(new SizeF(xTitleSize, yTitleSize));
 
			// Get absolute position of area
			RectangleF plotAreaRectAbs = chartGraph.GetAbsoluteRectangle( plotArea );
			RectangleF areaRectAbs = chartGraph.GetAbsoluteRectangle( chartAreaPosition.ToRectangleF());
 
			// Get absolute markers size and spacing
			float	spacing = chartGraph.GetAbsolutePoint(new PointF(0, this.AxisX.markSize + Axis.elementSpacing)).Y;
 
			// Get circular axis list
			ArrayList axisList = GetCircularAxisList();
 
			// Get circular axis labels style
			CircularAxisLabelsStyle labelsStyle = GetCircularAxisLabelsStyle();
 
			//*****************************************************************
			//** Calculate the auto-fit font if required
			//*****************************************************************
			if(this.AxisX.LabelStyle.Enabled && this.AxisX.IsLabelAutoFit)
			{
				// Set max auto fit font
				this.AxisX.autoLabelFont = Common.ChartPicture.FontCache.GetFont(
                    this.AxisX.LabelStyle.Font.FontFamily, 
					14, 
					this.AxisX.LabelStyle.Font.Style, 
					GraphicsUnit.Point);
 
				// Get estimated labels size
				float labelsSizeEstimate = GetCircularLabelsSize(chartGraph, areaRectAbs, plotAreaRectAbs, titleSize);
				labelsSizeEstimate = (float)Math.Min(labelsSizeEstimate * 1.1f, plotAreaRectAbs.Width / 5f);
				labelsSizeEstimate += spacing;
 
				// Calculate auto-fit font
				this.AxisX.GetCircularAxisLabelsAutoFitFont(chartGraph, axisList, labelsStyle, plotAreaRectAbs, areaRectAbs, labelsSizeEstimate);
			}
 
			//*****************************************************************
			//** Shrink plot area size proportionally
			//*****************************************************************
 
			// Get labels size
			float labelsSize = GetCircularLabelsSize(chartGraph, areaRectAbs, plotAreaRectAbs, titleSize);
 
			// Check if change size is smaller than radius
			labelsSize = (float)Math.Min(labelsSize, plotAreaRectAbs.Width / 2.5f);
			labelsSize += spacing;
			
			plotAreaRectAbs.X += labelsSize;
			plotAreaRectAbs.Width -= 2f * labelsSize;
			plotAreaRectAbs.Y += labelsSize;
			plotAreaRectAbs.Height -= 2f * labelsSize;
 
			// Restrict minimum plot area size
			if(plotAreaRectAbs.Width < 1.0f)
			{
				plotAreaRectAbs.Width = 1.0f;
			}
			if(plotAreaRectAbs.Height < 1.0f)
			{
				plotAreaRectAbs.Height = 1.0f;
			}
 
			plotArea = chartGraph.GetRelativeRectangle( plotAreaRectAbs );
			
 
			//*****************************************************************
			//** Set axes labels size
			//*****************************************************************
			SizeF	relativeLabelSize = chartGraph.GetRelativeSize(new SizeF(labelsSize, labelsSize));
			this.AxisX.labelSize = relativeLabelSize.Height;
			this.AxisX2.labelSize = relativeLabelSize.Height;
			this.AxisY.labelSize = relativeLabelSize.Width;
			this.AxisY2.labelSize = relativeLabelSize.Width;
 
		}
 
		/// <summary>
		/// Calculate size of the circular axis labels.
		/// </summary>
		/// <param name="chartGraph">Chart graphics object.</param>
		/// <param name="areaRectAbs">The Chart area position.</param>
		/// <param name="plotAreaRectAbs">Plotting area size.</param>
		/// <param name="titleSize">Size of title on the axes.</param>
		/// <returns>Circulat labels style.</returns>
		internal float GetCircularLabelsSize(
			ChartGraphics chartGraph, 
			RectangleF areaRectAbs, 
			RectangleF plotAreaRectAbs,
			SizeF titleSize)
		{
			// Find current horiz. and vert. spacing between plotting and chart areas
			SizeF	areaDiff = new SizeF(plotAreaRectAbs.X - areaRectAbs.X, plotAreaRectAbs.Y - areaRectAbs.Y);
			areaDiff.Width -= titleSize.Width;
			areaDiff.Height -= titleSize.Height;
 
			// Get absolute center of the area
			PointF	areaCenterAbs = chartGraph.GetAbsolutePoint(this.circularCenter);
 
			// Get circular axis list
			ArrayList axisList = GetCircularAxisList();
 
			// Get circular axis labels style
			CircularAxisLabelsStyle labelsStyle = GetCircularAxisLabelsStyle();
 
			// Defines on how much (pixels) the circular chart area radius should be reduced
			float	labelsSize = 0f;
 
			//*****************************************************************
			//** Loop through all axis labels
			//*****************************************************************
			foreach(CircularChartAreaAxis axis in axisList)
			{
				//*****************************************************************
				//** Measure label text
				//*****************************************************************
				SizeF	textSize = chartGraph.MeasureString(
					axis.Title.Replace("\\n", "\n"), 
					(this.AxisX.autoLabelFont == null) ? this.AxisX.LabelStyle.Font : this.AxisX.autoLabelFont);
				textSize.Width = (float)Math.Ceiling(textSize.Width * 1.1f);
				textSize.Height = (float)Math.Ceiling(textSize.Height * 1.1f);
 
 
				//*****************************************************************
				//** Calculate area size change depending on labels style
				//*****************************************************************
				if(labelsStyle == CircularAxisLabelsStyle.Circular)
				{
					labelsSize = (float)Math.Max(
						labelsSize, 
						textSize.Height);
				}
				else if(labelsStyle == CircularAxisLabelsStyle.Radial)
				{
					float textAngle = axis.AxisPosition + 90;
 
					// For angled text find it's X and Y components
					float	width = (float)Math.Cos(textAngle/180F*Math.PI) * textSize.Width;
					float	height = (float)Math.Sin(textAngle/180F*Math.PI) * textSize.Width;
					width = (float)Math.Abs(Math.Ceiling(width));
					height = (float)Math.Abs(Math.Ceiling(height));
 
					// Reduce text size by current spacing between plotting area and chart area
					width -= areaDiff.Width;
					height -= areaDiff.Height;
					if(width < 0)
						width = 0;
					if(height < 0)
						height = 0;
 
 
					labelsSize = (float)Math.Max(
						labelsSize, 
						Math.Max(width, height));
				}
				else if(labelsStyle == CircularAxisLabelsStyle.Horizontal)
				{
					// Get text angle
					float textAngle = axis.AxisPosition;
					if(textAngle > 180f)
					{
						textAngle -= 180f;
					}
 
					// Get label rotated position
					PointF[]	labelPosition = new PointF[] { new PointF(areaCenterAbs.X, plotAreaRectAbs.Y) };
					Matrix newMatrix = new Matrix();
					newMatrix.RotateAt(textAngle, areaCenterAbs);
					newMatrix.TransformPoints(labelPosition);
 
					// Calculate width
					float width = textSize.Width;
					width -= areaRectAbs.Right - labelPosition[0].X;
					if(width < 0f)
					{
						width = 0f;
					}
 
					labelsSize = (float)Math.Max(
						labelsSize, 
						Math.Max(width, textSize.Height));
				}
			}
 
			return labelsSize;
		}
 
		/// <summary>
		/// True if polygons should be used instead of the circles for the chart area.
		/// </summary>
		internal bool CircularUsePolygons
		{
			get
			{
				// Check if value was precalculated
				if(this._circularUsePolygons == int.MinValue)
				{
					_circularUsePolygons = 0;
 
					// Look for custom properties in series
					foreach(Series series in this.Common.DataManager.Series)
					{
						if(series.ChartArea == this.Name && series.IsVisible())
						{
							// Get custom attribute
                            if (series.IsCustomPropertySet(CustomPropertyName.AreaDrawingStyle))
							{
								if(String.Compare(series[CustomPropertyName.AreaDrawingStyle], "Polygon", StringComparison.OrdinalIgnoreCase) == 0)
								{
									_circularUsePolygons = 1;
								}
                                else if (String.Compare(series[CustomPropertyName.AreaDrawingStyle], "Circle", StringComparison.OrdinalIgnoreCase) == 0)
								{
									_circularUsePolygons = 0;
								}
								else
								{
									throw(new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid( series[CustomPropertyName.AreaDrawingStyle], "AreaDrawingStyle")));
								}
								break;
							}
						}
					}
				}
 
				return (this._circularUsePolygons == 1);
			}
		}
 
		/// <summary>
		/// Gets circular area axis labels style.
		/// </summary>
		/// <returns>Axis labels style.</returns>
		internal CircularAxisLabelsStyle GetCircularAxisLabelsStyle()
		{
			CircularAxisLabelsStyle	style = CircularAxisLabelsStyle.Auto;
 
			// Get maximum number of points in all series
			foreach(Series series in this.Common.DataManager.Series)
			{
				if(series.IsVisible() && series.ChartArea == this.Name && series.IsCustomPropertySet(CustomPropertyName.CircularLabelsStyle))
				{
					string styleName = series[CustomPropertyName.CircularLabelsStyle];
					if(String.Compare( styleName, "Auto", StringComparison.OrdinalIgnoreCase) == 0 )
					{
						style = CircularAxisLabelsStyle.Auto;
					}
					else if(String.Compare( styleName,"Circular", StringComparison.OrdinalIgnoreCase) == 0)
					{
						style = CircularAxisLabelsStyle.Circular;
					}
					else if(String.Compare( styleName,"Radial", StringComparison.OrdinalIgnoreCase) == 0)
					{
						style = CircularAxisLabelsStyle.Radial;
					}
                    else if (String.Compare(styleName, "Horizontal", StringComparison.OrdinalIgnoreCase) == 0)
					{
						style = CircularAxisLabelsStyle.Horizontal;
					}
					else
					{
						throw(new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid( styleName, "CircularLabelsStyle")));
					}
					
				}
			}
 
			// Get auto style
			if(style == CircularAxisLabelsStyle.Auto)
			{
				int	sectorNumber = CircularSectorsNumber;
				style = CircularAxisLabelsStyle.Horizontal;
				if(sectorNumber > 30)
				{
					style = CircularAxisLabelsStyle.Radial;
				}
			}
 
			return style;
		}
 
		/// <summary>
		/// Number of sectors in the circular area.
		/// </summary>
		internal int CircularSectorsNumber
		{
			get
			{
				// Check if value was precalculated
				if(this._circularSectorNumber == int.MinValue)
				{
					this._circularSectorNumber = GetCircularSectorNumber();
				}
 
				return this._circularSectorNumber;
			}
		}
 
		/// <summary>
		/// Gets number of sectors in the circular chart area.
		/// </summary>
		/// <returns>Number of sectors.</returns>
		private int GetCircularSectorNumber()
		{
			ICircularChartType type = this.GetCircularChartType();
			if(type != null)
			{
				return type.GetNumerOfSectors(this, this.Common.DataManager.Series);
			}
			return 0;
		}
 
		/// <summary>
		/// Fills a list of circular axis.
		/// </summary>
		/// <returns>Axes list.</returns>
		internal ArrayList GetCircularAxisList()
		{
			// Check if list was already created
			if(_circularAxisList == null)
			{
				_circularAxisList = new ArrayList();
 
				// Loop through all sectors
				int sectorNumber = GetCircularSectorNumber();
				for(int sectorIndex = 0; sectorIndex < sectorNumber; sectorIndex++)
				{
					// Create new axis object
					CircularChartAreaAxis	axis = new CircularChartAreaAxis(sectorIndex * 360f/sectorNumber);
 
					// Check if custom X axis labels will be used
					if(this.AxisX.CustomLabels.Count > 0)
					{
						if(sectorIndex < this.AxisX.CustomLabels.Count)
						{
							axis.Title = this.AxisX.CustomLabels[sectorIndex].Text;
                            axis.TitleForeColor = this.AxisX.CustomLabels[sectorIndex].ForeColor;
						}
					}
					else
					{
						// Get axis title from all series
						foreach(Series series in this.Common.DataManager.Series)
						{
							if(series.IsVisible() && series.ChartArea == this.Name && sectorIndex < series.Points.Count)
							{
								if(series.Points[sectorIndex].AxisLabel.Length > 0)
								{
									axis.Title = series.Points[sectorIndex].AxisLabel;
									break;
								}
							}
						}
					}
 
					// Add axis into the list
					_circularAxisList.Add(axis);
				}
 
			}
			return _circularAxisList;
		}
 
		/// <summary>
		/// Converts circular position of the X axis to angle in degrees.
		/// </summary>
		/// <param name="position">X axis position.</param>
		/// <returns>Angle in degrees.</returns>
		internal float CircularPositionToAngle(double position)
		{
			// Get X axis scale size
			double scaleRatio = 360.0 / Math.Abs(this.AxisX.Maximum - this.AxisX.Minimum);
			
			return (float)(position * scaleRatio + this.AxisX.Crossing);
		}
 
#endregion
 
#region 2D Series drawing order methods
 
            /// <summary>
            /// Helper method that returns a list of 'ChartTypeAndSeriesInfo' objects.
            /// This list is used for chart area series drawing in 2D mode. Each
            /// object may represent an individual series or all series that belong
            /// to one chart type.
            /// 
            /// This method is intended to fix issues #6443 and #5385 when area chart 
            /// type incorrectly overlaps point or line chart type.
            /// </summary>
            /// <returns>List of 'ChartTypeAndSeriesInfo' objects.</returns>
            private ArrayList GetChartTypesAndSeriesToDraw()
            {
                ArrayList resultList = new ArrayList();
 
                // Build chart type or series position based lists
                if (this.ChartTypes.Count > 1 &&
                    (this.ChartTypes.Contains(ChartTypeNames.Area) 
                    || this.ChartTypes.Contains(ChartTypeNames.SplineArea)
                    )
                    )
                {
                    // Array of chart type names that do not require furher processing
                    ArrayList processedChartType = new ArrayList();
                    ArrayList splitChartType = new ArrayList();
 
                    // Draw using the exact order in the series collection
                    int seriesIndex = 0;
                    foreach (Series series in this.Common.DataManager.Series)
                    {
                        // Check if series is visible and belongs to the chart area
                        if (series.ChartArea==this.Name && series.IsVisible() && series.Points.Count > 0)
                        {
                            // Check if this chart type was already processed
                            if (!processedChartType.Contains(series.ChartTypeName))
                            {
                                // Check if curent chart type can be individually processed
                                bool canBeIndividuallyProcessed = false;
                                if (series.ChartType == SeriesChartType.Point ||
                                    series.ChartType == SeriesChartType.Line ||
                                    series.ChartType == SeriesChartType.Spline ||
                                    series.ChartType == SeriesChartType.StepLine)
                                {
                                    canBeIndividuallyProcessed = true;
                                }
 
                                if (!canBeIndividuallyProcessed)
                                {
                                    // Add a record to process all series of that chart type at once
                                    resultList.Add(new ChartTypeAndSeriesInfo(series.ChartTypeName));
                                    processedChartType.Add(series.ChartTypeName);
                                }
                                else
                                {
                                    // Check if curent chart type has more that 1 series and they are split 
                                    // by other series
                                    bool chartTypeIsSplit = false;
 
                                    if (splitChartType.Contains(series.ChartTypeName))
                                    {
                                        chartTypeIsSplit = true;
                                    }
                                    else
                                    {
                                        bool otherChartTypeFound = false;
                                        for (int curentSeriesIndex = seriesIndex + 1; curentSeriesIndex < this.Common.DataManager.Series.Count; curentSeriesIndex++)
                                        {
                                            if (series.ChartTypeName == this.Common.DataManager.Series[curentSeriesIndex].ChartTypeName)
                                            {
                                                if (otherChartTypeFound)
                                                {
                                                    chartTypeIsSplit = true;
                                                    splitChartType.Add(series.ChartTypeName);
                                                }
                                            }
                                            else
                                            {
                                                if (this.Common.DataManager.Series[curentSeriesIndex].ChartType == SeriesChartType.Area ||
                                                    this.Common.DataManager.Series[curentSeriesIndex].ChartType == SeriesChartType.SplineArea)
                                                {
                                                    otherChartTypeFound = true;
                                                }
                                            }
                                        }
                                    }
 
                                    if (chartTypeIsSplit)
                                    {
                                        // Add a record to process this series individually
                                        resultList.Add(new ChartTypeAndSeriesInfo(series));
                                    }
                                    else
                                    {
                                        // Add a record to process all series of that chart type at once
                                        resultList.Add(new ChartTypeAndSeriesInfo(series.ChartTypeName));
                                        processedChartType.Add(series.ChartTypeName);
                                    }
                                }
                            }
                        }
 
                        ++seriesIndex;
                    }
                }
                else
                {
                    foreach (string chartType in this.ChartTypes)
                    {
                        resultList.Add(new ChartTypeAndSeriesInfo(chartType));
                    }
                }
 
                return resultList;
            }
 
            /// <summary>
            /// Internal data structure that stores chart type name and optionally series object.
            /// </summary>
            internal class ChartTypeAndSeriesInfo
            {
                /// <summary>
                /// Object constructor.
                /// </summary>
                public ChartTypeAndSeriesInfo()
                {
                }
 
                /// <summary>
                /// Object constructor.
                /// </summary>
                /// <param name="chartType">Chart type name to initialize with.</param>
                public ChartTypeAndSeriesInfo(string chartType)
                {
                    this.ChartType = chartType;
                }
 
                /// <summary>
                /// Object constructor.
                /// </summary>
                /// <param name="series">Series to initialize with.</param>
                public ChartTypeAndSeriesInfo(Series series)
                {
                    this.ChartType = series.ChartTypeName;
                    this.Series = series;
                }
 
                // Chart type name
                internal string ChartType = string.Empty;
 
                // Series object. Can be set to NULL!
                internal Series Series = null;
 
            }
 
#endregion // 2D Series drawing order methods
 
#region IDisposable Members
 
            /// <summary>
            /// Releases unmanaged and - optionally - managed resources
            /// </summary>
            /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "axisX")]
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "axisX2")]
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "axisY")]
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "axisY2")]
            protected override void Dispose(bool disposing)
            {
                if (disposing)
                {
                    // Dispose managed resources
                    if (this._axisArray != null)
                    {
                        foreach (Axis axis in this._axisArray)
                        {
                            axis.Dispose();
                        }
                        this._axisArray = null;
                    }
                    if ( this._areaPosition != null)
                    {
                        this._areaPosition.Dispose();
                        this._areaPosition = null;
                    }
                    if (this._innerPlotPosition != null)
                    {
                        this._innerPlotPosition.Dispose();
                        this._innerPlotPosition = null;
                    }
                    if (this.PlotAreaPosition != null)
                    {
                        this.PlotAreaPosition.Dispose();
                        this.PlotAreaPosition = null;
                    }
#if Microsoft_CONTROL
                    if (this.areaBufferBitmap != null)
                    {
                        this.areaBufferBitmap.Dispose();
                        this.areaBufferBitmap = null;
                    }
                    if (this._cursorX != null)
                    {
                        this._cursorX.Dispose();
                        this._cursorX = null;
                    }
                    if (this._cursorY != null)
                    {
                        this._cursorY.Dispose();
                        this._cursorY = null;
                    }
#endif
                }
                base.Dispose(disposing);
            }
 
 
#endregion
 
        }
}