Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Web.DataVisualization / Common / General / ChartArea.cs
1 //-------------------------------------------------------------
2 // <copyright company=\92Microsoft Corporation\92>
3 //   Copyright © Microsoft Corporation. All Rights Reserved.
4 // </copyright>
5 //-------------------------------------------------------------
6 // @owner=alexgor, deliant
7 //=================================================================
8 //  File:               ChartArea.cs
9 //
10 //  Namespace:  System.Web.UI.WebControls[Windows.Forms].Charting
11 //
12 //      Classes:        ChartArea
13 //
14 //  Purpose:    The ChartArea class represents one chart area within 
15 //              a chart image, and is used to plot one or more chart 
16 //              series. The number of chart series that can be plotted 
17 //              in a chart area is unlimited.
18 //
19 //      Reviewed:       GS - August 6, 2002
20 //                              AG - August 7, 2002
21 //              AG - Microsoft 16, 2007
22 //
23 //===================================================================
24
25 #region Used namespaces
26 using System;
27 using System.Collections;
28 using System.Collections.Specialized;
29 using System.ComponentModel;
30 using System.ComponentModel.Design;
31 using System.Data;
32 using System.Drawing;
33 using System.Drawing.Design;
34 using System.Drawing.Drawing2D;
35 using System.Globalization;
36 using System.Diagnostics.CodeAnalysis;
37
38 #if Microsoft_CONTROL
39
40         using System.Windows.Forms.DataVisualization.Charting.Data;
41         using System.Windows.Forms.DataVisualization.Charting.ChartTypes;
42         using System.Windows.Forms.DataVisualization.Charting.Utilities;
43         using System.Windows.Forms.DataVisualization.Charting.Borders3D;
44         using System.Windows.Forms.DataVisualization.Charting;
45         using System.ComponentModel.Design.Serialization;
46         using System.Reflection;
47         using System.Windows.Forms.Design;
48 #else
49         using System.Web;
50         using System.Web.UI;
51         using System.Web.UI.DataVisualization.Charting;
52         using System.Web.UI.DataVisualization.Charting.Data;
53         using System.Web.UI.DataVisualization.Charting.ChartTypes;
54         using System.Web.UI.DataVisualization.Charting.Utilities;
55         using System.Web.UI.DataVisualization.Charting.Borders3D;
56 #endif
57
58
59 #endregion
60
61 #if Microsoft_CONTROL
62         namespace System.Windows.Forms.DataVisualization.Charting
63 #else
64 namespace System.Web.UI.DataVisualization.Charting
65 #endif
66 {
67         #region Chart area aligment enumerations
68
69     /// <summary>
70     /// An enumeration of the alignment orientations of a ChartArea
71     /// </summary>
72                 [Flags]
73                 public enum AreaAlignmentOrientations
74                 {
75                         /// <summary>
76             /// Chart areas are not automatically aligned.
77                         /// </summary>
78                         None = 0,
79
80                         /// <summary>
81             /// Chart areas are aligned vertically.
82                         /// </summary>
83                         Vertical = 1,
84
85                         /// <summary>
86             /// Chart areas are aligned horizontally.
87                         /// </summary>
88                         Horizontal = 2,
89
90                         /// <summary>
91             /// Chart areas are aligned using all values (horizontally and vertically).
92                         /// </summary>
93                         All = Vertical | Horizontal
94                 }
95
96         /// <summary>
97         /// An enumeration of the alignment styles of a ChartArea
98         /// </summary>
99                 [Flags]
100                 public enum AreaAlignmentStyles
101                 {
102                         /// <summary>
103             /// Chart areas are not automatically aligned.
104                         /// </summary>
105                         None = 0,
106
107                         /// <summary>
108             /// Chart areas are aligned by positions.
109                         /// </summary>
110                         Position = 1,
111
112                         /// <summary>
113             /// Chart areas are aligned by inner plot positions.
114                         /// </summary>
115                         PlotPosition = 2,
116
117             /// <summary>
118             /// Chart areas are aligned by axes views.
119             /// </summary>
120             AxesView = 4,
121
122 #if Microsoft_CONTROL
123
124                         /// <summary>
125                         /// Cursor and Selection alignment.
126                         /// </summary>
127                         Cursor = 8,
128
129                         /// <summary>
130                         /// Complete alignment.
131                         /// </summary>
132                         All = Position | PlotPosition | Cursor | AxesView
133 #else // Microsoft_CONTROL
134
135                         /// <summary>
136                         /// Complete alignment.
137                         /// </summary>
138             All = Position | PlotPosition | AxesView
139
140 #endif // Microsoft_CONTROL
141         }
142
143         #endregion
144
145         /// <summary>
146         /// The ChartArea class is used to create and display a chart 
147         /// area within a chart image. The chart area is a rectangular 
148         /// area on a chart image.  It has 4 axes, horizontal and vertical grids. 
149     /// A chart area can contain more than one different chart type.  
150     /// The number of chart series that can be plotted in a chart area 
151     /// is unlimited.
152     /// 
153     /// ChartArea class exposes all the properties and methods
154     /// of its base ChartArea3D class.
155         /// </summary>
156                 [
157                 DefaultProperty("Axes"),
158                 SRDescription("DescriptionAttributeChartArea_ChartArea"),
159                 ]
160 #if ASPPERM_35
161         [AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
162         [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
163 #endif
164         public partial class ChartArea : ChartNamedElement
165                 {
166                     #region Chart Area Fields
167
168             /// <summary>
169             /// Plot area position
170             /// </summary>
171             internal ElementPosition PlotAreaPosition;
172
173                         // Private data members, which store properties values
174                         private Axis[]                                  _axisArray = new Axis[4];
175                         private Color                                   _backColor = Color.Empty;
176                         private ChartHatchStyle                 _backHatchStyle = ChartHatchStyle.None;
177                         private string                                  _backImage = "";
178                         private ChartImageWrapMode              _backImageWrapMode = ChartImageWrapMode.Tile;
179                         private Color                                   _backImageTransparentColor = Color.Empty;
180                         private ChartImageAlignmentStyle                        _backImageAlignment = ChartImageAlignmentStyle.TopLeft;
181                         private GradientStyle                   _backGradientStyle = GradientStyle.None;
182                         private Color                                   _backSecondaryColor = Color.Empty;
183                         private Color                                   _borderColor = Color.Black;
184                         private int                                             _borderWidth = 1;
185                         private ChartDashStyle                  _borderDashStyle = ChartDashStyle.NotSet;
186                         private int                                             _shadowOffset = 0;
187                         private Color                                   _shadowColor = Color.FromArgb(128, 0, 0, 0);
188                         private ElementPosition                 _areaPosition = null;
189                         private ElementPosition                 _innerPlotPosition = null;
190                         internal int                                    IterationCounter = 0;
191
192                         private         bool                            _isSameFontSizeForAllAxes = false;
193                         internal        float                           axesAutoFontSize = 8f;
194
195             private string                      _alignWithChartArea = Constants.NotSetValue;
196                         private         AreaAlignmentOrientations       _alignmentOrientation = AreaAlignmentOrientations.Vertical;
197                         private         AreaAlignmentStyles                     _alignmentStyle = AreaAlignmentStyles.All;
198                         private         int                                             _circularSectorNumber = int.MinValue;
199                         private         int                                             _circularUsePolygons = int.MinValue;
200
201                         // Flag indicates that chart area is acurrently aligned
202                         internal        bool                                    alignmentInProcess = false;
203
204                         // Chart area position before adjustments
205                         internal        RectangleF                              originalAreaPosition = RectangleF.Empty;
206
207                         // Chart area inner plot position before adjustments
208                         internal        RectangleF                              originalInnerPlotPosition = RectangleF.Empty;
209
210             // Chart area position before adjustments
211             internal    RectangleF              lastAreaPosition = RectangleF.Empty;
212
213
214                         // Center of the circulat chart area
215                         internal        PointF                                  circularCenter = PointF.Empty;
216
217                         private         ArrayList                               _circularAxisList = null;
218
219 #if Microsoft_CONTROL
220                         // Buffered plotting area image
221                         internal                Bitmap                          areaBufferBitmap = null;
222
223             private     Cursor                      _cursorX = new Cursor();
224             private Cursor                      _cursorY = new Cursor();
225 #endif
226
227             // Area SmartLabel class
228                         internal                SmartLabel                      smartLabels = new SmartLabel();
229
230                         // Gets or sets a flag that specifies whether the chart area is visible.
231                         private                 bool                            _visible = true;
232
233                 #endregion
234
235                     #region Chart Area Cursor properties
236
237 #if Microsoft_CONTROL
238
239                         /// <summary>
240                         /// Gets or sets a Cursor object that is used for cursors and selected ranges along the X-axis.
241                         /// </summary>
242                         [
243                         SRCategory("CategoryAttributeCursor"),
244                         Bindable(true),
245                         DefaultValue(null),
246                         SRDescription("DescriptionAttributeChartArea_CursorX"),
247                         DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
248                         TypeConverter(typeof(NoNameExpandableObjectConverter)),
249                         ]
250                         public Cursor CursorX
251                         {
252                                 get
253                                 {
254                                         return _cursorX;
255                                 }
256                                 set
257                                 {
258                                         _cursorX = value;
259
260                                         // Initialize chart object
261                                         _cursorX.Initialize(this, AxisName.X);
262                                 }
263                         }
264
265                         /// <summary>
266                         /// Gets or sets a Cursor object that is used for cursors and selected ranges along the Y-axis.
267                         /// </summary>
268                         [
269                         SRCategory("CategoryAttributeCursor"),
270                         Bindable(true),
271                         DefaultValue(null),
272                         SRDescription("DescriptionAttributeChartArea_CursorY"),
273                         DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
274                         TypeConverter(typeof(NoNameExpandableObjectConverter)),
275                         ]
276                         public Cursor CursorY
277                         {
278                                 get
279                                 {
280                                         return _cursorY;
281                                 }
282                                 set
283                                 {
284                                         _cursorY = value;
285
286                                         // Initialize chart object
287                                         _cursorY.Initialize(this, AxisName.Y);
288                                 }
289                         }
290
291 #endif // Microsoft_CONTROL
292
293             #endregion
294
295             #region Chart Area properties
296
297                         /// <summary>
298                         /// Gets or sets a flag that specifies whether the chart area is visible.
299                         /// </summary>
300                         /// <remarks>
301                         /// When this flag is set to false, all series, legends, titles and annotation objects 
302                         /// associated with the chart area will also be hidden.
303                         /// </remarks>
304                         /// <value>
305                         /// <b>True</b> if the chart area is visible; <b>false</b> otherwise.
306                         /// </value>
307                         [
308                         SRCategory("CategoryAttributeAppearance"),
309                         DefaultValue(true),
310                         SRDescription("DescriptionAttributeChartArea_Visible"),
311                         ParenthesizePropertyNameAttribute(true),
312                         ]
313                         virtual public bool Visible
314                         {
315                                 get
316                                 {
317                                         return _visible;
318                                 }
319                                 set
320                                 {
321                                         _visible = value;
322                                         this.Invalidate();
323                                 }
324                         }
325
326                         /// <summary>
327             /// Gets or sets the name of the ChartArea object to which this chart area should be aligned.
328                         /// </summary>
329                         [
330                         SRCategory("CategoryAttributeAlignment"),
331                         Bindable(true),
332             DefaultValue(Constants.NotSetValue),
333                         SRDescription("DescriptionAttributeChartArea_AlignWithChartArea"),
334                         TypeConverter(typeof(LegendAreaNameConverter)),
335                 #if !Microsoft_CONTROL
336                 PersistenceMode(PersistenceMode.Attribute)
337                 #endif
338                         ]
339                         public string AlignWithChartArea
340                         {
341                                 get
342                                 {
343                                         return _alignWithChartArea;
344                                 }
345                                 set
346                                 {
347                     if (value != _alignWithChartArea)
348                     {
349                         if (String.IsNullOrEmpty(value))
350                         {
351                             _alignWithChartArea = Constants.NotSetValue;
352                         }
353                         else
354                         {
355                             if (Chart != null && Chart.ChartAreas != null)
356                             {
357                                 Chart.ChartAreas.VerifyNameReference(value);
358                             }
359                             _alignWithChartArea = value;
360                         }
361                         Invalidate();
362                     }
363                                 }
364                         }
365
366                         /// <summary>
367             /// Gets or sets the alignment orientation of a chart area.
368                         /// </summary>
369                         [
370             SRCategory("CategoryAttributeAlignment"),
371                         Bindable(true),
372                         DefaultValue(AreaAlignmentOrientations.Vertical),
373                         SRDescription("DescriptionAttributeChartArea_AlignOrientation"),
374             Editor(Editors.FlagsEnumUITypeEditor.Editor, Editors.FlagsEnumUITypeEditor.Base),
375                     #if !Microsoft_CONTROL
376                     PersistenceMode(PersistenceMode.Attribute)
377                     #endif
378                         ]
379                         public AreaAlignmentOrientations        AlignmentOrientation
380                         {
381                                 get
382                                 {
383                                         return _alignmentOrientation;
384                                 }
385                                 set
386                                 {
387                                         _alignmentOrientation = value;
388                                         Invalidate();
389                                 }
390                         }
391
392
393                         /// <summary>
394                         /// Gets or sets the alignment style of the ChartArea.
395                         /// </summary>
396                         [
397             SRCategory("CategoryAttributeAlignment"),
398                         Bindable(true),
399                         DefaultValue(AreaAlignmentStyles.All),
400                         SRDescription("DescriptionAttributeChartArea_AlignType"),
401             Editor(Editors.FlagsEnumUITypeEditor.Editor, Editors.FlagsEnumUITypeEditor.Base),
402                 #if !Microsoft_CONTROL
403                 PersistenceMode(PersistenceMode.Attribute)
404                 #endif
405                         ]
406                         public AreaAlignmentStyles AlignmentStyle
407                         {
408                                 get
409                                 {
410                                         return _alignmentStyle;
411                                 }
412                                 set
413                                 {
414                                         _alignmentStyle = value;
415                                         Invalidate();
416                                 }
417                         }
418
419                         /// <summary>
420             /// Gets or sets an array that represents all axes for a chart area.
421                         /// </summary>
422                         [
423                         SRCategory("CategoryAttributeAxes"),
424                         Bindable(true),
425                         SRDescription("DescriptionAttributeChartArea_Axes"),
426                         TypeConverter(typeof(AxesArrayConverter)),
427             Editor(Editors.AxesArrayEditor.Editor, Editors.AxesArrayEditor.Base),
428                         DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
429                         SerializationVisibilityAttribute(SerializationVisibility.Hidden)
430                         ]
431             [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
432                         public Axis[] Axes
433                         {
434                                 get
435                                 {
436                                         return _axisArray;
437                                 }
438                                 set
439                                 {
440                                         AxisX = value[0];
441                                         AxisY = value[1];
442                                         AxisX2 = value[2];
443                                         AxisY2 = value[3];
444                                         Invalidate();
445                                 }
446                         }
447
448                         /// <summary>
449                         /// Avoid serialization of the axes array
450                         /// </summary>
451             [EditorBrowsableAttribute(EditorBrowsableState.Never)]
452                         internal bool ShouldSerializeAxes()
453                         {
454                                 return false;
455                         }
456
457                         /// <summary>
458             /// Gets or sets an Axis object that represents the primary Y-axis. 
459                         /// </summary>
460                         [
461                         SRCategory("CategoryAttributeAxis"),
462                         Bindable(true),
463                         Browsable(false),
464                         SRDescription("DescriptionAttributeChartArea_AxisY"),
465 #if Microsoft_CONTROL
466                         DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
467 #else
468                 PersistenceMode(PersistenceMode.InnerProperty),
469 #endif
470                         TypeConverter(typeof(NoNameExpandableObjectConverter))
471                         ]
472                         public Axis AxisY
473                         {
474                                 get
475                                 {
476                                         return axisY;
477                                 }
478                                 set
479                                 {
480                                         axisY = value;
481                                         axisY.Initialize(this, AxisName.Y);
482                                         _axisArray[1] = axisY;
483                                         Invalidate();
484                                 }
485                         }
486
487                         /// <summary>
488             /// Gets or sets an Axis object that represents the primary X-axis. 
489                         /// </summary>
490                         [
491                         SRCategory("CategoryAttributeAxis"),
492                         Bindable(true),
493                         Browsable(false),
494                         SRDescription("DescriptionAttributeChartArea_AxisX"),
495 #if Microsoft_CONTROL
496                         DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
497 #else
498                 PersistenceMode(PersistenceMode.InnerProperty),
499 #endif
500                         TypeConverter(typeof(NoNameExpandableObjectConverter))
501                         ]
502                         public Axis AxisX
503                         {
504                                 get
505                                 {
506                                         return axisX;
507                                 }
508                                 set
509                                 {
510                                         axisX = value;
511                                         axisX.Initialize(this, AxisName.X);
512                                         _axisArray[0] = axisX;
513                                         Invalidate();
514                                 }
515                         }
516
517                         /// <summary>
518             /// Gets or sets an Axis object that represents the secondary X-axis. 
519                         /// </summary>
520                         [
521                         SRCategory("CategoryAttributeAxis"),
522                         Bindable(true),
523                         Browsable(false),
524                         SRDescription("DescriptionAttributeChartArea_AxisX2"),
525 #if Microsoft_CONTROL
526                         DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
527 #else
528                 PersistenceMode(PersistenceMode.InnerProperty),
529 #endif
530                         TypeConverter(typeof(NoNameExpandableObjectConverter))
531                         ]
532                         public Axis AxisX2
533                         {
534                                 get
535                                 {
536                                         return axisX2;
537                                 }
538                                 set
539                                 {
540                                         axisX2 = value;
541                                         axisX2.Initialize(this, AxisName.X2);
542                                         _axisArray[2] = axisX2;
543                                         Invalidate();
544                                 }
545                         }
546
547                         /// <summary>
548             /// Gets or sets an Axis object that represents the secondary Y-axis.
549                         /// </summary>
550                         [
551                         SRCategory("CategoryAttributeAxis"),
552                         Bindable(true),
553                         Browsable(false),
554                         SRDescription("DescriptionAttributeChartArea_AxisY2"),
555 #if Microsoft_CONTROL
556                         DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
557 #else
558                 PersistenceMode(PersistenceMode.InnerProperty),
559 #endif
560                         TypeConverter(typeof(NoNameExpandableObjectConverter))
561                         ]
562                         public Axis AxisY2
563                         {
564                                 get
565                                 {
566                                         return axisY2;
567                                 }
568                                 set
569                                 {
570                                         axisY2 = value;
571                                         axisY2.Initialize(this, AxisName.Y2);
572                                         _axisArray[3] = axisY2;
573                                         Invalidate();
574                                 }
575                         }
576
577                         /// <summary>
578             /// Gets or sets an ElementPosition object, which defines the position of a chart area object within the chart image.
579                         /// </summary>
580                         [
581                         SRCategory("CategoryAttributeAppearance"),
582                         Bindable(true),
583                         SRDescription("DescriptionAttributeChartArea_Position"),
584 #if Microsoft_CONTROL
585                         DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
586 #else
587                     PersistenceMode(PersistenceMode.InnerProperty),
588 #endif
589                         NotifyParentPropertyAttribute(true),
590                         TypeConverter(typeof(ElementPositionConverter)),
591                         SerializationVisibilityAttribute(SerializationVisibility.Element)
592                         ]
593                         public ElementPosition Position
594                         {
595                                 get
596                                 {       
597                                         // Serialize only position values if Auto set to false
598                                         if(this.Chart != null && this.Chart.serializationStatus == SerializationStatus.Saving )
599                                         {
600                                                 if(_areaPosition.Auto)
601                                                 {
602                                                         return new ElementPosition();   
603                                                 }
604                                                 else
605                                                 {
606                                                         ElementPosition newPosition = new ElementPosition();
607 #if Microsoft_CONTROL
608                                                         newPosition.Auto = false;
609 #else
610                                                 newPosition.Auto = true;
611 #endif
612                                                         newPosition.SetPositionNoAuto(_areaPosition.X, _areaPosition.Y, _areaPosition.Width, _areaPosition.Height);
613                                                         return newPosition;
614                                                 }
615                                         }
616                                         return _areaPosition;
617                                 }
618                                 set
619                                 {
620                                         _areaPosition = value;
621                                         _areaPosition.Parent = this;
622                                         _areaPosition.resetAreaAutoPosition = true;
623                                         Invalidate();
624                                 }
625                         }
626
627             /// <summary>
628             /// Determoines if this position should be serialized.
629             /// </summary>
630             /// <returns></returns>
631             internal bool ShouldSerializePosition()
632             {
633                 return !this.Position.Auto;
634             }
635
636                         /// <summary>
637             /// Gets or sets an ElementPosition object, which defines the inner plot position of a chart area object.  
638                         /// </summary>
639                         [
640                         SRCategory("CategoryAttributeAppearance"),
641                         Bindable(true),
642                         SRDescription("DescriptionAttributeChartArea_InnerPlotPosition"),
643 #if Microsoft_CONTROL
644                         DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
645 #else
646                     PersistenceMode(PersistenceMode.InnerProperty),
647 #endif
648                         NotifyParentPropertyAttribute(true),
649                         TypeConverter(typeof(ElementPositionConverter)),
650                         SerializationVisibilityAttribute(SerializationVisibility.Element)
651                         ]
652                         public ElementPosition InnerPlotPosition
653                         {
654                                 get
655                                 {       
656                                         // Serialize only position values if Auto set to false
657                     if (this.Common != null && this.Common.Chart != null && this.Common.Chart.serializationStatus == SerializationStatus.Saving)
658                                         {
659                                                 if(_innerPlotPosition.Auto)
660                                                 {
661                                                         return new ElementPosition();   
662                                                 }
663                                                 else
664                                                 {
665                                                         ElementPosition newPosition = new ElementPosition();
666 #if Microsoft_CONTROL
667                                                         newPosition.Auto = false;
668 #else
669                                                 newPosition.Auto = true;
670 #endif
671                                                         newPosition.SetPositionNoAuto(_innerPlotPosition.X, _innerPlotPosition.Y, _innerPlotPosition.Width, _innerPlotPosition.Height);
672                                                         return newPosition;
673                                                 }
674                                         }
675                                         return _innerPlotPosition;
676                                 }
677                                 set
678                                 {
679                                         _innerPlotPosition = value;
680                                         _innerPlotPosition.Parent = this;
681                                         Invalidate();
682                                 }
683                         }
684
685             /// <summary>
686             /// Determoines if this position should be serialized.
687             /// </summary>
688             /// <returns></returns>
689             internal bool ShouldSerializeInnerPlotPosition()
690             {
691                 return !this.InnerPlotPosition.Auto;
692             }
693
694                         /// <summary>
695             /// Gets or sets the background color of a ChartArea object. 
696                         /// </summary>
697                         [
698
699                         SRCategory("CategoryAttributeAppearance"),
700                         Bindable(true),
701                         DefaultValue(typeof(Color), ""),
702             SRDescription("DescriptionAttributeBackColor"),
703                         NotifyParentPropertyAttribute(true),
704             TypeConverter(typeof(ColorConverter)),
705             Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
706                 #if !Microsoft_CONTROL
707                 PersistenceMode(PersistenceMode.Attribute)
708                 #endif
709                         ]
710                         public Color BackColor
711                         {
712                                 get
713                                 {
714                                         return _backColor;
715                                 }
716                                 set
717                                 {
718                                         _backColor = value;
719                                         Invalidate();
720                                 }
721                         }
722
723                         /// <summary>
724             /// Gets or sets the hatching style of a ChartArea object.
725                         /// </summary>
726                         [
727
728
729                         SRCategory("CategoryAttributeAppearance"),
730                         Bindable(true),
731                         DefaultValue(ChartHatchStyle.None),
732                         NotifyParentPropertyAttribute(true),
733             SRDescription("DescriptionAttributeBackHatchStyle"),
734                 #if !Microsoft_CONTROL
735                 PersistenceMode(PersistenceMode.Attribute),
736                 #endif
737             Editor(Editors.HatchStyleEditor.Editor, Editors.HatchStyleEditor.Base)
738
739                         ]
740                         public ChartHatchStyle BackHatchStyle
741                         {
742                                 get
743                                 {
744                                         return _backHatchStyle;
745                                 }
746                                 set
747                                 {
748                                         _backHatchStyle = value;
749                                         Invalidate();
750                                 }
751                         }
752
753                         /// <summary>
754             /// Gets or sets the background image of a ChartArea object. 
755                         /// </summary>
756                         [
757                         SRCategory("CategoryAttributeAppearance"),
758                         Bindable(true),
759                         DefaultValue(""),
760             SRDescription("DescriptionAttributeBackImage"),
761             Editor(Editors.ImageValueEditor.Editor, Editors.ImageValueEditor.Base),
762 #if !Microsoft_CONTROL
763                 PersistenceMode(PersistenceMode.Attribute),
764 #endif
765                         NotifyParentPropertyAttribute(true)
766                         ]
767                         public string BackImage
768                         {
769                                 get
770                                 {
771                                         return _backImage;
772                                 }
773                                 set
774                                 {
775                                         _backImage = value;
776                                         Invalidate();
777                                 }
778                         }
779
780                         /// <summary>
781             /// Gets or sets the drawing mode of the background image of a ChartArea object.
782                         /// </summary>
783                         [
784                         SRCategory("CategoryAttributeAppearance"),
785                         Bindable(true),
786                         DefaultValue(ChartImageWrapMode.Tile),
787                         NotifyParentPropertyAttribute(true),
788             SRDescription("DescriptionAttributeImageWrapMode"),
789                 #if !Microsoft_CONTROL
790                 PersistenceMode(PersistenceMode.Attribute)
791                 #endif
792                         ]
793                         public ChartImageWrapMode BackImageWrapMode
794                         {
795                                 get
796                                 {
797                                         return _backImageWrapMode;
798                                 }
799                                 set
800                                 {
801                                         _backImageWrapMode = value;
802                                         Invalidate();
803                                 }
804                         }
805
806                         /// <summary>
807             /// Gets or sets the color of a ChartArea object's background image that will be drawn as transparent.  
808                         /// </summary>
809                         [
810                         SRCategory("CategoryAttributeAppearance"),
811                         Bindable(true),
812                         DefaultValue(typeof(Color), ""),
813                         NotifyParentPropertyAttribute(true),
814             SRDescription("DescriptionAttributeImageTransparentColor"),
815             TypeConverter(typeof(ColorConverter)),
816             Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
817                 #if !Microsoft_CONTROL
818                 PersistenceMode(PersistenceMode.Attribute)
819                 #endif
820                         ]
821                         public Color BackImageTransparentColor
822                         {
823                                 get
824                                 {
825                                         return _backImageTransparentColor;
826                                 }
827                                 set
828                                 {
829                                         _backImageTransparentColor = value;
830                                         Invalidate();
831                                 }
832                         }
833
834                         /// <summary>
835             /// Gets or sets the alignment of a ChartArea object. 
836                         /// </summary>
837                         [
838                         SRCategory("CategoryAttributeAppearance"),
839                         Bindable(true),
840                         DefaultValue(ChartImageAlignmentStyle.TopLeft),
841                         NotifyParentPropertyAttribute(true),
842             SRDescription("DescriptionAttributeBackImageAlign"),
843                 #if !Microsoft_CONTROL
844                 PersistenceMode(PersistenceMode.Attribute)
845                 #endif
846                         ]
847                         public ChartImageAlignmentStyle BackImageAlignment
848                         {
849                                 get
850                                 {
851                                         return _backImageAlignment;
852                                 }
853                                 set
854                                 {
855                                         _backImageAlignment = value;
856                                         Invalidate();
857                                 }
858                         }
859
860                         /// <summary>
861             /// Gets or sets the orientation of a chart element's gradient, 
862             /// and also determines whether or not a gradient is used.  
863                         /// </summary>
864                         [
865
866             SRCategory("CategoryAttributeAppearance"),
867                         Bindable(true),
868                         DefaultValue(GradientStyle.None),
869                         NotifyParentPropertyAttribute(true),
870             SRDescription("DescriptionAttributeBackGradientStyle"),
871                 #if !Microsoft_CONTROL
872                 PersistenceMode(PersistenceMode.Attribute),
873                 #endif
874             Editor(Editors.GradientEditor.Editor, Editors.GradientEditor.Base)
875                         ]               
876                         public GradientStyle BackGradientStyle
877                         {
878                                 get
879                                 {
880                                         return _backGradientStyle;
881                                 }
882                                 set
883                                 {
884                                         _backGradientStyle = value;
885                                         Invalidate();
886                                 }
887                         }
888
889                         /// <summary>
890             /// Gets or sets the secondary color of a ChartArea object.
891                         /// </summary>
892                         [
893
894             SRCategory("CategoryAttributeAppearance"),
895                         Bindable(true),
896                         DefaultValue(typeof(Color), ""),
897                         NotifyParentPropertyAttribute(true),
898             SRDescription("DescriptionAttributeBackSecondaryColor"),
899             TypeConverter(typeof(ColorConverter)),
900             Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
901                 #if !Microsoft_CONTROL
902                 PersistenceMode(PersistenceMode.Attribute)
903                 #endif
904                         ] 
905                         public Color BackSecondaryColor
906                         {
907                                 get
908                                 {
909                                         return _backSecondaryColor;
910                                 }
911                                 set
912                                 {
913                                         _backSecondaryColor = value;
914                                         Invalidate();
915                                 }
916                         }
917
918                         /// <summary>
919             /// Gets or sets the shadow color of a ChartArea object.  
920                         /// </summary>
921                         [
922                         SRCategory("CategoryAttributeAppearance"),
923                         Bindable(true),
924                         DefaultValue(typeof(Color), "128,0,0,0"),
925             SRDescription("DescriptionAttributeShadowColor"),
926                         NotifyParentPropertyAttribute(true),
927             TypeConverter(typeof(ColorConverter)),
928             Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
929                 #if !Microsoft_CONTROL
930                 PersistenceMode(PersistenceMode.Attribute)
931                 #endif
932                         ]
933                         public Color ShadowColor
934                         {
935                                 get
936                                 {
937                                         return _shadowColor;
938                                 }
939                                 set
940                                 {
941                                         _shadowColor = value;
942                                         Invalidate();
943                                 }
944                         }
945
946                         /// <summary>
947             /// Gets or sets the shadow offset (in pixels) of a ChartArea object.
948                         /// </summary>
949                         [
950                         SRCategory("CategoryAttributeAppearance"),
951                         Bindable(true),
952                         DefaultValue(0),
953             SRDescription("DescriptionAttributeShadowOffset"),
954                         NotifyParentPropertyAttribute(true),
955                 #if !Microsoft_CONTROL
956                 PersistenceMode(PersistenceMode.Attribute)
957                 #endif
958                         ]
959                         public int ShadowOffset
960                         {
961                                 get
962                                 {
963                                         return _shadowOffset;
964                                 }
965                                 set
966                                 {
967                                         _shadowOffset = value;
968                                         Invalidate();
969                                 }
970                         }
971
972                         /// <summary>
973             /// Gets or sets the border color of a ChartArea object.
974                         /// </summary>
975                         [
976
977             SRCategory("CategoryAttributeAppearance"),
978                         Bindable(true),
979                         DefaultValue(typeof(Color), "Black"),
980             SRDescription("DescriptionAttributeBorderColor"),
981                         NotifyParentPropertyAttribute(true),
982             TypeConverter(typeof(ColorConverter)),
983             Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
984                 #if !Microsoft_CONTROL
985                 PersistenceMode(PersistenceMode.Attribute)
986                 #endif
987                         ]
988                         public Color BorderColor
989                         {
990                                 get
991                                 {
992                                         return _borderColor;
993                                 }
994                                 set
995                                 {
996                                         _borderColor = value;
997                                         Invalidate();
998                                 }
999                         }
1000
1001                         /// <summary>
1002             /// Gets or sets the border width of a ChartArea object.
1003                         /// </summary>
1004                         [
1005
1006                         SRCategory("CategoryAttributeAppearance"),
1007                         Bindable(true),
1008                         DefaultValue(1),
1009             SRDescription("DescriptionAttributeBorderWidth"),
1010                         NotifyParentPropertyAttribute(true),
1011                 #if !Microsoft_CONTROL
1012                 PersistenceMode(PersistenceMode.Attribute)
1013                 #endif
1014                         ]
1015                         public int BorderWidth
1016                         {
1017                                 get
1018                                 {
1019                                         return _borderWidth;
1020                                 }
1021                                 set
1022                                 {
1023                                         if(value < 0)
1024                                         {
1025                         throw (new ArgumentOutOfRangeException("value", SR.ExceptionBorderWidthIsNegative));
1026                                         }
1027                                         _borderWidth = value;
1028                                         Invalidate();
1029                                 }
1030                         }
1031
1032                         /// <summary>
1033             /// Gets or sets the style of the border line of a ChartArea object.
1034                         /// </summary>
1035                         [
1036
1037             SRCategory("CategoryAttributeAppearance"),
1038                         Bindable(true),
1039                         DefaultValue(ChartDashStyle.NotSet),
1040             SRDescription("DescriptionAttributeBorderDashStyle"),
1041                         NotifyParentPropertyAttribute(true),
1042                 #if !Microsoft_CONTROL
1043                 PersistenceMode(PersistenceMode.Attribute)
1044                 #endif
1045                         ]
1046                         public ChartDashStyle BorderDashStyle
1047                         {
1048                                 get
1049                                 {
1050                                         return _borderDashStyle;
1051                                 }
1052                                 set
1053                                 {
1054                                         _borderDashStyle = value;
1055                                         Invalidate();
1056                                 }
1057                         }
1058
1059                         /// <summary>
1060             /// Gets or sets the unique name of a ChartArea object.
1061                         /// </summary>
1062                         [
1063
1064                         SRCategory("CategoryAttributeMisc"),
1065                         Bindable(true),
1066                         SRDescription("DescriptionAttributeChartArea_Name"),
1067                         NotifyParentPropertyAttribute(true),
1068                 #if !Microsoft_CONTROL
1069                 PersistenceMode(PersistenceMode.Attribute)
1070                 #endif
1071                         ]
1072                         public override string Name
1073                         {
1074                                 get
1075                                 {
1076                                         return base.Name;
1077                                 }
1078                                 set
1079                                 {
1080                     base.Name = value;
1081                                 }
1082                         }
1083
1084             /// <summary>
1085             /// Gets or sets a Boolean that determines if the labels of the axes for all chart area
1086             /// , which have LabelsAutoFit property set to true, are of equal size.  
1087             /// </summary>
1088                         [
1089                         SRCategory("CategoryAttributeAppearance"),
1090                         Bindable(true),
1091                         DefaultValue(false),
1092                         SRDescription("DescriptionAttributeChartArea_EquallySizedAxesFont"),
1093                         NotifyParentPropertyAttribute(true),
1094                 #if !Microsoft_CONTROL
1095                 PersistenceMode(PersistenceMode.Attribute)
1096                 #endif
1097                         ]
1098                         public bool IsSameFontSizeForAllAxes
1099                         {
1100                                 get
1101                                 {
1102                                         return _isSameFontSizeForAllAxes;
1103                                 }
1104                                 set
1105                                 {
1106                                         _isSameFontSizeForAllAxes = value;
1107                                         Invalidate();
1108                                 }
1109                         }
1110
1111
1112                 #endregion
1113
1114             #region Constructors
1115             /// <summary>
1116                         /// ChartArea constructor.
1117                         /// </summary>
1118                         public ChartArea()
1119                         {
1120                                 Initialize();
1121                         }
1122
1123             /// <summary>
1124             /// ChartArea constructor.
1125             /// </summary>
1126             /// <param name="name">The name.</param>
1127             public ChartArea(string name) : base(name)
1128             {
1129                 Initialize();
1130             }
1131             #endregion
1132
1133             #region Chart Area Methods
1134                         /// <summary>
1135                         /// Restores series order and X axis reversed mode for the 3D charts.
1136                         /// </summary>
1137                         internal void Restore3DAnglesAndReverseMode()
1138                         {
1139                                 if(this.Area3DStyle.Enable3D && !this.chartAreaIsCurcular)
1140                                 {
1141                                         // Restore axis "IsReversed" property and old Y angle
1142                                         this.AxisX.IsReversed = oldReverseX;
1143                                         this.AxisX2.IsReversed = oldReverseX;
1144                                         this.AxisY.IsReversed = oldReverseY;
1145                                         this.AxisY2.IsReversed = oldReverseY;
1146                                         this.Area3DStyle.Rotation = oldYAngle;
1147                                 }
1148                         }
1149         
1150                         /// <summary>
1151                         /// Sets series order and X axis reversed mode for the 3D charts.
1152                         /// </summary>
1153                         internal void Set3DAnglesAndReverseMode()
1154                         {
1155                                 // Clear series reversed flag
1156                                 _reverseSeriesOrder = false;
1157
1158                                 // If 3D charting is enabled
1159                                 if(this.Area3DStyle.Enable3D)
1160                                 {
1161                                         // Make sure primary & secondary axis has the same IsReversed settings
1162                                         // This is a limitation for the 3D chart required for labels drawing.
1163                                         this.AxisX2.IsReversed = this.AxisX.IsReversed;
1164                                         this.AxisY2.IsReversed = this.AxisY.IsReversed;
1165
1166                                         // Remember reversed order of X & Y axis and Angles
1167                                         oldReverseX = this.AxisX.IsReversed;
1168                                         oldReverseY = this.AxisY.IsReversed;
1169                                         oldYAngle = this.Area3DStyle.Rotation;
1170
1171                                         // Check if Y angle 
1172                                         if(this.Area3DStyle.Rotation > 90 || this.Area3DStyle.Rotation < -90)
1173                                         {
1174                         // This method depends on the 'switchValueAxes' field which is calculated based on the chart types
1175                         // of the series associated with the chart area. We need to call SetData method to make sure this field
1176                         // is correctly initialized. Because we only need to collect information about the series, we pass 'false'
1177                         // as parameters to limit the amount of work this function does.
1178                         this.SetData(false, false);
1179
1180                                                 // Reversed series order
1181                                                 _reverseSeriesOrder = true;
1182
1183                                                 // Reversed primary and secondary X axis
1184                                                 if(!this.switchValueAxes)
1185                                                 {
1186                                                         this.AxisX.IsReversed = !this.AxisX.IsReversed;
1187                                                         this.AxisX2.IsReversed = !this.AxisX2.IsReversed;
1188                                                 }
1189
1190                                                         // Reversed primary and secondary Y axis for chart types like Bar
1191                                                 else
1192                                                 {
1193                                                         this.AxisY.IsReversed = !this.AxisY.IsReversed;
1194                                                         this.AxisY2.IsReversed = !this.AxisY2.IsReversed;
1195                                                 }
1196
1197                                                 // Adjust Y angle
1198                                                 if(this.Area3DStyle.Rotation > 90)
1199                                                 {
1200                                                         this.Area3DStyle.Rotation = (this.Area3DStyle.Rotation - 90) - 90;
1201                                                 }
1202                                                 else if(this.Area3DStyle.Rotation < -90)
1203                                                 {
1204                                                         this.Area3DStyle.Rotation = (this.Area3DStyle.Rotation + 90) + 90;
1205                                                 }
1206                                         }
1207                                 }
1208                         }
1209
1210                         /// <summary>
1211                         /// Save all automatic values like Minimum and Maximum.
1212                         /// </summary>
1213                         internal void SetTempValues()
1214                         {
1215                                 // Save non automatic area position
1216                                 if(!this.Position.Auto)
1217                                 {
1218                                         this.originalAreaPosition = this.Position.ToRectangleF();
1219                                 }
1220
1221                                 // Save non automatic area inner plot position
1222                                 if(!this.InnerPlotPosition.Auto)
1223                                 {
1224                                         this.originalInnerPlotPosition = this.InnerPlotPosition.ToRectangleF();
1225                                 }
1226                         
1227                                 this._circularSectorNumber = int.MinValue;
1228                                 this._circularUsePolygons = int.MinValue;
1229                                 this._circularAxisList = null;
1230
1231                                 // Save Minimum and maximum values for all axes
1232                                 axisX.StoreAxisValues();
1233                                 axisX2.StoreAxisValues();
1234                                 axisY.StoreAxisValues();
1235                                 axisY2.StoreAxisValues();
1236                         }
1237
1238                         /// <summary>
1239                         /// Load all automatic values like Minimum and Maximum with original values.
1240                         /// </summary>
1241                         internal void GetTempValues()
1242                         {
1243                                 // Take Minimum and maximum values for all axes
1244                                 axisX.ResetAxisValues();
1245                                 axisX2.ResetAxisValues();
1246                                 axisY.ResetAxisValues();
1247                                 axisY2.ResetAxisValues();
1248
1249                                 // Restore non automatic area position
1250                                 if(!this.originalAreaPosition.IsEmpty)
1251                                 {
1252                     this.lastAreaPosition = this.Position.ToRectangleF();
1253                     this.Position.SetPositionNoAuto(this.originalAreaPosition.X, this.originalAreaPosition.Y, this.originalAreaPosition.Width, this.originalAreaPosition.Height);
1254                                         this.originalAreaPosition = RectangleF.Empty;
1255                                 }
1256
1257                                 // Save non automatic area inner plot position
1258                                 if(!this.originalInnerPlotPosition.IsEmpty)
1259                                 {
1260                     this.InnerPlotPosition.SetPositionNoAuto(this.originalInnerPlotPosition.X, this.originalInnerPlotPosition.Y, this.originalInnerPlotPosition.Width, this.originalInnerPlotPosition.Height);
1261                                         this.originalInnerPlotPosition = RectangleF.Empty;
1262                                 }
1263                         }
1264                 
1265                         /// <summary>
1266                         /// Initialize Chart area and axes
1267                         /// </summary>
1268                         internal void Initialize()
1269                         {
1270                 // Initialize 3D style class
1271                 _area3DStyle = new ChartArea3DStyle(this);
1272
1273                                 // Create axes for this chart area.
1274                                 axisY = new Axis( );
1275                                 axisX = new Axis( );
1276                                 axisX2 = new Axis( );
1277                                 axisY2 = new Axis( );
1278
1279                                 // Initialize axes;
1280                                 axisX.Initialize(this, AxisName.X);
1281                                 axisY.Initialize(this, AxisName.Y);
1282                                 axisX2.Initialize(this, AxisName.X2);
1283                                 axisY2.Initialize(this, AxisName.Y2);
1284
1285                                 // Initialize axes array
1286                                 _axisArray[0] = axisX;
1287                                 _axisArray[1] = axisY;
1288                                 _axisArray[2] = axisX2;
1289                                 _axisArray[3] = axisY2;
1290
1291                                 // Set flag to reset auto values for all areas
1292                 _areaPosition = new ElementPosition(this);
1293                                 _areaPosition.resetAreaAutoPosition = true;
1294
1295                 _innerPlotPosition = new ElementPosition(this);
1296                         
1297                                 // Set the position of the new chart area
1298                                 if( PlotAreaPosition == null )
1299                                 {
1300                                         PlotAreaPosition = new ElementPosition(this);
1301                                 }
1302         
1303 #if Microsoft_CONTROL
1304
1305                                 // Initialize cursor class
1306                 this._cursorX.Initialize(this, AxisName.X);
1307                 this._cursorY.Initialize(this, AxisName.Y);
1308
1309 #endif // Microsoft_CONTROL
1310                         }
1311
1312                         /// <summary>
1313                         /// Minimum and maximum do not have to be calculated 
1314                         /// from data series every time. It is very time 
1315                         /// consuming. Minimum and maximum are buffered 
1316                         /// and only when this flags are set Minimum and 
1317                         /// Maximum are refreshed from data.
1318                         /// </summary>
1319                         internal void ResetMinMaxFromData()
1320                         {
1321                                 _axisArray[0].refreshMinMaxFromData = true;
1322                                 _axisArray[1].refreshMinMaxFromData = true;
1323                                 _axisArray[2].refreshMinMaxFromData = true;
1324                                 _axisArray[3].refreshMinMaxFromData = true;
1325                         }
1326
1327                         /// <summary>
1328                         /// Recalculates the axes scale of a chart area.
1329                         /// </summary>
1330                         public void RecalculateAxesScale()
1331                         {
1332                                 // Read axis Max/Min from data
1333                                 ResetMinMaxFromData();
1334
1335 #if Microsoft_CONTROL
1336                                 Set3DAnglesAndReverseMode();
1337                                 SetTempValues();
1338 #endif
1339
1340                                 // Initialize area position
1341                                 _axisArray[0].ReCalc( PlotAreaPosition );
1342                                 _axisArray[1].ReCalc( PlotAreaPosition );
1343                                 _axisArray[2].ReCalc( PlotAreaPosition );
1344                                 _axisArray[3].ReCalc( PlotAreaPosition );
1345                         
1346                                 // Find all Data and chart types which belong 
1347                                 // to this chart area an set default values
1348                                 SetData();
1349
1350 #if Microsoft_CONTROL
1351                                 Restore3DAnglesAndReverseMode();
1352                                 GetTempValues();
1353 #endif
1354                         }
1355
1356                         /// <summary>
1357                         /// RecalculateAxesScale the chart area
1358                         /// </summary>
1359                         internal void ReCalcInternal()
1360                         {
1361                                 // Initialize area position
1362                                 _axisArray[0].ReCalc( PlotAreaPosition );
1363                                 _axisArray[1].ReCalc( PlotAreaPosition );
1364                                 _axisArray[2].ReCalc( PlotAreaPosition );
1365                                 _axisArray[3].ReCalc( PlotAreaPosition );
1366                         
1367                                 // Find all Data and chart types which belong 
1368                                 // to this chart area an set default values
1369                                 SetData();
1370                         }
1371
1372
1373                         /// <summary>
1374                         /// Reset auto calculated chart area values.
1375                         /// </summary>
1376                         internal void ResetAutoValues()
1377                         {
1378                                 _axisArray[0].ResetAutoValues();
1379                                 _axisArray[1].ResetAutoValues();
1380                                 _axisArray[2].ResetAutoValues();
1381                                 _axisArray[3].ResetAutoValues();
1382                         }
1383
1384                         /// <summary>
1385                         /// Calculates Position for the background.
1386                         /// </summary>
1387                         /// <param name="withScrollBars">Calculate with scroll bars</param>
1388                         /// <returns>Background rectangle</returns>
1389                         internal RectangleF GetBackgroundPosition( bool withScrollBars )
1390                         {
1391                                 // For pie and doughnut, which do not have axes, the position 
1392                                 // for the background is Chart area position not plotting 
1393                                 // area position.
1394                                 RectangleF backgroundPosition = PlotAreaPosition.ToRectangleF();
1395                                 if( !requireAxes )
1396                                 {
1397                                         backgroundPosition = Position.ToRectangleF();
1398                                 }
1399
1400                 // Without scroll bars
1401                                 if( !withScrollBars )
1402                                 {
1403                                         return backgroundPosition;
1404                                 }
1405
1406                                 // Add scroll bar rectangles to the area background 
1407                                 RectangleF backgroundPositionWithScrollBars = new RectangleF(backgroundPosition.Location, backgroundPosition.Size);
1408
1409 #if Microsoft_CONTROL
1410
1411                                 if( requireAxes )
1412                                 {
1413                                         // Loop through all axis
1414                                         foreach(Axis axis in this.Axes)
1415                                         {
1416                                                 // Find axis with visible scroll bars
1417                                                 if(axis.ScrollBar.IsVisible && axis.ScrollBar.IsPositionedInside)
1418                                                 {
1419                                                         // Change size of the background rectangle depending on the axis position
1420                                                         if(axis.AxisPosition == AxisPosition.Bottom)
1421                                                         {
1422                                                                 backgroundPositionWithScrollBars.Height += (float)axis.ScrollBar.GetScrollBarRelativeSize();
1423                                                         }
1424                                                         else if(axis.AxisPosition == AxisPosition.Top)
1425                                                         {
1426                                                                 backgroundPositionWithScrollBars.Y -= (float)axis.ScrollBar.GetScrollBarRelativeSize();
1427                                                                 backgroundPositionWithScrollBars.Height += (float)axis.ScrollBar.GetScrollBarRelativeSize();
1428                                                         }
1429                                                         else if(axis.AxisPosition == AxisPosition.Left)
1430                                                         {
1431                                                                 backgroundPositionWithScrollBars.X -= (float)axis.ScrollBar.GetScrollBarRelativeSize();
1432                                                                 backgroundPositionWithScrollBars.Width += (float)axis.ScrollBar.GetScrollBarRelativeSize();
1433                                                         }
1434                                                         else if(axis.AxisPosition == AxisPosition.Left)
1435                                                         {
1436                                                                 backgroundPositionWithScrollBars.Width += (float)axis.ScrollBar.GetScrollBarRelativeSize();
1437                                                         }
1438                                                 }
1439                                         }
1440                                 }
1441
1442 #endif // Microsoft_CONTROL
1443                                 return backgroundPositionWithScrollBars;
1444                         }
1445
1446                         /// <summary>
1447                         /// Call when the chart area is resized.
1448                         /// </summary>
1449                         /// <param name="chartGraph">Chart graphics object.</param>
1450                         internal void Resize(ChartGraphics chartGraph)
1451                         {
1452                                 // Initialize plotting area position
1453                                 RectangleF plottingRect = Position.ToRectangleF();
1454                                 if(!InnerPlotPosition.Auto)
1455                                 {
1456                                         plottingRect.X += (Position.Width / 100F) * InnerPlotPosition.X;
1457                                         plottingRect.Y += (Position.Height / 100F) * InnerPlotPosition.Y;
1458                                         plottingRect.Width = (Position.Width / 100F) * InnerPlotPosition.Width;
1459                                         plottingRect.Height = (Position.Height / 100F) * InnerPlotPosition.Height;
1460                                 }
1461
1462                                 //******************************************************
1463                                 //** Calculate number of vertical and horizontal axis
1464                                 //******************************************************
1465                                 int     verticalAxes = 0;
1466                                 int     horizontalAxes = 0;
1467                                 foreach(Axis axis in this.Axes)
1468                                 {
1469                                         if(axis.enabled)
1470                                         {
1471                                                 if(axis.AxisPosition == AxisPosition.Bottom)
1472                                                 {
1473                                                         ++horizontalAxes;               
1474                                                 }
1475                                                 else if(axis.AxisPosition == AxisPosition.Top)
1476                                                 {
1477                                                         ++horizontalAxes;
1478                                                 }
1479                                                 else if(axis.AxisPosition == AxisPosition.Left)
1480                                                 {
1481                                                         ++verticalAxes;
1482                                                 }
1483                                                 else if(axis.AxisPosition == AxisPosition.Right)
1484                                                 {
1485                                                         ++verticalAxes;
1486                                                 }
1487                                         }
1488                                 }
1489                                 if(horizontalAxes <= 0 )
1490                                 {
1491                                         horizontalAxes = 1;
1492                                 }
1493                                 if(verticalAxes <= 0 )
1494                                 {
1495                                         verticalAxes = 1;
1496                                 }
1497
1498
1499                                 //******************************************************
1500                                 //** Find same auto-fit font size
1501                                 //******************************************************
1502                                 Axis[] axisArray = (this.switchValueAxes) ? 
1503                                         new Axis[] {this.AxisX, this.AxisX2, this.AxisY, this.AxisY2} :
1504                                         new Axis[] {this.AxisY, this.AxisY2, this.AxisX, this.AxisX2};
1505                                 if(this.IsSameFontSizeForAllAxes)
1506                                 {
1507                                         axesAutoFontSize = 20;
1508                                         foreach(Axis axis in axisArray)
1509                                         {
1510                                                 // Process only enabled axis
1511                                                 if(axis.enabled)
1512                                                 {
1513                                                         // Resize axis
1514                                                         if(axis.AxisPosition == AxisPosition.Bottom || axis.AxisPosition == AxisPosition.Top)
1515                                                         {
1516                                                                 axis.Resize(chartGraph, this.PlotAreaPosition, plottingRect, horizontalAxes, InnerPlotPosition.Auto);
1517                                                         }
1518                                                         else
1519                                                         {
1520                                                                 axis.Resize(chartGraph, this.PlotAreaPosition, plottingRect, verticalAxes, InnerPlotPosition.Auto);
1521                                                         }
1522
1523                                                         // Calculate smallest font size
1524                                                         if(axis.IsLabelAutoFit && axis.autoLabelFont != null)
1525                                                         {
1526                                                                 axesAutoFontSize = Math.Min(axesAutoFontSize, axis.autoLabelFont.Size);
1527                                                         }
1528                                                 }
1529                                         }
1530                                 }
1531
1532                                 //******************************************************
1533                                 //** Adjust plotting area position according to the axes 
1534                                 //** elements (title, labels, tick marks) size.
1535                                 //******************************************************
1536                                 RectangleF      rectLabelSideSpacing = RectangleF.Empty;
1537                                 foreach(Axis axis in axisArray)
1538                                 {
1539                                         // Process only enabled axis
1540                                         if( ! axis.enabled )
1541                                         {
1542                                                 //******************************************************
1543                                                 //** Adjust for the 3D Wall Width for disabled axis
1544                                                 //******************************************************
1545                                                 if(InnerPlotPosition.Auto && this.Area3DStyle.Enable3D && !this.chartAreaIsCurcular)
1546                                                 {
1547                                                         SizeF areaWallSize = chartGraph.GetRelativeSize(new SizeF(this.Area3DStyle.WallWidth, this.Area3DStyle.WallWidth));
1548                                                         if(axis.AxisPosition == AxisPosition.Bottom)
1549                                                         {
1550                                                                 plottingRect.Height -= areaWallSize.Height;
1551                                                         }
1552                                                         else if(axis.AxisPosition == AxisPosition.Top)
1553                                                         {
1554                                                                 plottingRect.Y += areaWallSize.Height;
1555                                                                 plottingRect.Height -= areaWallSize.Height;
1556                                                         }
1557                                                         else if(axis.AxisPosition == AxisPosition.Right)
1558                                                         {
1559                                                                 plottingRect.Width -= areaWallSize.Width;
1560                                                         }
1561                                                         else if(axis.AxisPosition == AxisPosition.Left)
1562                                                         {
1563                                                                 plottingRect.X += areaWallSize.Width;
1564                                                                 plottingRect.Width -= areaWallSize.Width;
1565                                                         }
1566                                                 }
1567
1568                                                 continue;
1569                                         }
1570
1571                                         //******************************************************
1572                                         //** Calculate axes elements position
1573                                         //******************************************************
1574                                         if(axis.AxisPosition == AxisPosition.Bottom || axis.AxisPosition == AxisPosition.Top)
1575                                         {
1576                                                 axis.Resize(chartGraph, this.PlotAreaPosition, plottingRect, horizontalAxes, InnerPlotPosition.Auto);
1577                                         }
1578                                         else
1579                                         {
1580                                                 axis.Resize(chartGraph, this.PlotAreaPosition, plottingRect, verticalAxes, InnerPlotPosition.Auto);
1581                                         }
1582
1583                                         // Shift top/bottom labels so they will not overlap with left/right labels
1584                                         PreventTopBottomAxesLabelsOverlapping(axis);
1585
1586                                         //******************************************************
1587                                         //** Check axis position
1588                                         //******************************************************
1589                                         float axisPosition = (float)axis.GetAxisPosition();
1590                                         if(axis.AxisPosition == AxisPosition.Bottom)
1591                                         {
1592                                                 if(!axis.GetIsMarksNextToAxis())
1593                                                 {
1594                                                         axisPosition = plottingRect.Bottom;
1595                                                 }
1596                                                 axisPosition = plottingRect.Bottom - axisPosition;
1597                                         }
1598                                         else if(axis.AxisPosition == AxisPosition.Top)
1599                                         {
1600                                                 if(!axis.GetIsMarksNextToAxis())
1601                                                 {
1602                                                         axisPosition = plottingRect.Y;
1603                                                 }
1604                                                 axisPosition = axisPosition - plottingRect.Top;
1605                                         }
1606                                         else if(axis.AxisPosition == AxisPosition.Right)
1607                                         {
1608                                                 if(!axis.GetIsMarksNextToAxis())
1609                                                 {
1610                                                         axisPosition = plottingRect.Right;
1611                                                 }
1612                                                 axisPosition = plottingRect.Right - axisPosition;
1613                                         }
1614                                         else if(axis.AxisPosition == AxisPosition.Left)
1615                                         {
1616                                                 if(!axis.GetIsMarksNextToAxis())
1617                                                 {
1618                                                         axisPosition = plottingRect.X;
1619                                                 }
1620                                                 axisPosition = axisPosition - plottingRect.Left;
1621                                         }
1622
1623                                         //******************************************************
1624                                         //** Adjust axis elements size with axis position
1625                                         //******************************************************
1626                                         // Calculate total size of axis elements
1627                                         float axisSize = axis.markSize + axis.labelSize;
1628
1629 #if SUBAXES
1630                                         // Add sub-axis size
1631                                         if(!this.chartAreaIsCurcular && !this.Area3DStyle.Enable3D)
1632                                         {
1633                                                 foreach(SubAxis subAxis in axis.SubAxes)
1634                                                 {
1635                                                         axisSize += subAxis.markSize + subAxis.labelSize + subAxis.titleSize;
1636                                                 }
1637                                         }
1638 #endif // SUBAXES
1639
1640                     // Adjust depending on the axis position
1641                                         axisSize -= axisPosition;
1642                                         if(axisSize < 0)
1643                                         {
1644                                                 axisSize = 0;
1645                                         }
1646
1647
1648                                         // Add axis title and scroll bar size (always outside of plotting area)
1649                                         axisSize += axis.titleSize + axis.scrollBarSize;
1650
1651
1652                                         // Calculate horizontal axes size for circualar area
1653                                         if(this.chartAreaIsCurcular && 
1654                                                 (axis.AxisPosition == AxisPosition.Top || axis.AxisPosition == AxisPosition.Bottom) )
1655                                         {
1656                                                 axisSize = axis.titleSize + axis.markSize + axis.scrollBarSize;
1657                                         }
1658
1659                                         //******************************************************
1660                                         //** Adjust plotting area
1661                                         //******************************************************
1662                                         if(InnerPlotPosition.Auto)
1663                                         {
1664                                                 if(axis.AxisPosition == AxisPosition.Bottom)
1665                                                 {
1666                                                         plottingRect.Height -= axisSize;
1667                                                 }
1668                                                 else if(axis.AxisPosition == AxisPosition.Top)
1669                                                 {
1670                                                         plottingRect.Y += axisSize;
1671                                                         plottingRect.Height -= axisSize;
1672                                                 }
1673                                                 else if(axis.AxisPosition == AxisPosition.Left)
1674                                                 {
1675                                                         plottingRect.X += axisSize;
1676                                                         plottingRect.Width -= axisSize;
1677                                                 }
1678                                                 else if(axis.AxisPosition == AxisPosition.Right)
1679                                                 {
1680                                                         plottingRect.Width -= axisSize;
1681                                                 }
1682
1683                         // Check if labels side offset should be processed
1684                         bool addLabelsSideOffsets = true;
1685
1686                                                 // Update the plotting area depending on the size required for labels on the sides
1687                         if (addLabelsSideOffsets)
1688                         {
1689                             if (axis.AxisPosition == AxisPosition.Bottom || axis.AxisPosition == AxisPosition.Top)
1690                             {
1691                                 if (axis.labelNearOffset != 0 && axis.labelNearOffset < Position.X)
1692                                 {
1693                                     float offset = Position.X - axis.labelNearOffset;
1694                                     if (Math.Abs(offset) > plottingRect.Width * 0.3f)
1695                                     {
1696                                         offset = plottingRect.Width * 0.3f;
1697                                     }
1698
1699                                     // NOTE: Code was removed to solve an issue with extra space when labels angle = 45
1700                                     //rectLabelSideSpacing.Width = (float)Math.Max(offset, rectLabelSideSpacing.Width);
1701                                     rectLabelSideSpacing.X = (float)Math.Max(offset, rectLabelSideSpacing.X);
1702                                 }
1703
1704                                 if (axis.labelFarOffset > Position.Right)
1705                                 {
1706                                     if ((axis.labelFarOffset - Position.Right) < plottingRect.Width * 0.3f)
1707                                     {
1708                                         rectLabelSideSpacing.Width = (float)Math.Max(axis.labelFarOffset - Position.Right, rectLabelSideSpacing.Width);
1709                                     }
1710                                     else
1711                                     {
1712                                         rectLabelSideSpacing.Width = (float)Math.Max(plottingRect.Width * 0.3f, rectLabelSideSpacing.Width);
1713                                     }
1714                                 }
1715                             }
1716
1717                             else
1718                             {
1719                                 if (axis.labelNearOffset != 0 && axis.labelNearOffset < Position.Y)
1720                                 {
1721                                     float offset = Position.Y - axis.labelNearOffset;
1722                                     if (Math.Abs(offset) > plottingRect.Height * 0.3f)
1723                                     {
1724                                         offset = plottingRect.Height * 0.3f;
1725                                     }
1726
1727                                     // NOTE: Code was removed to solve an issue with extra space when labels angle = 45
1728                                     //rectLabelSideSpacing.Height = (float)Math.Max(offset, rectLabelSideSpacing.Height);
1729                                     rectLabelSideSpacing.Y = (float)Math.Max(offset, rectLabelSideSpacing.Y);
1730                                 }
1731
1732                                 if (axis.labelFarOffset > Position.Bottom)
1733                                 {
1734                                     if ((axis.labelFarOffset - Position.Bottom) < plottingRect.Height * 0.3f)
1735                                     {
1736                                         rectLabelSideSpacing.Height = (float)Math.Max(axis.labelFarOffset - Position.Bottom, rectLabelSideSpacing.Height);
1737                                     }
1738                                     else
1739                                     {
1740                                         rectLabelSideSpacing.Height = (float)Math.Max(plottingRect.Height * 0.3f, rectLabelSideSpacing.Height);
1741                                     }
1742                                 }
1743                             }
1744                         }
1745                                         }
1746                                 }
1747
1748                                 //******************************************************
1749                                 //** Make sure there is enough space 
1750                                 //** for labels on the chart sides
1751                                 //******************************************************
1752                 if (!this.chartAreaIsCurcular)
1753                 {
1754                     if (rectLabelSideSpacing.Y > 0 && rectLabelSideSpacing.Y > plottingRect.Y - Position.Y)
1755                     {
1756                         float delta = (plottingRect.Y - Position.Y) - rectLabelSideSpacing.Y;
1757                         plottingRect.Y -= delta;
1758                         plottingRect.Height += delta;
1759                     }
1760                     if (rectLabelSideSpacing.X > 0 && rectLabelSideSpacing.X > plottingRect.X - Position.X)
1761                     {
1762                         float delta = (plottingRect.X - Position.X) - rectLabelSideSpacing.X;
1763                         plottingRect.X -= delta;
1764                         plottingRect.Width += delta;
1765                     }
1766                     if (rectLabelSideSpacing.Height > 0 && rectLabelSideSpacing.Height > Position.Bottom - plottingRect.Bottom)
1767                     {
1768                         plottingRect.Height += (Position.Bottom - plottingRect.Bottom) - rectLabelSideSpacing.Height;
1769                     }
1770                     if (rectLabelSideSpacing.Width > 0 && rectLabelSideSpacing.Width > Position.Right - plottingRect.Right)
1771                     {
1772                         plottingRect.Width += (Position.Right - plottingRect.Right) - rectLabelSideSpacing.Width;
1773                     }
1774                 }
1775
1776                                 //******************************************************
1777                                 //** Plotting area must be square for the circular 
1778                                 //** chart area (in pixels).
1779                                 //******************************************************
1780                                 if(this.chartAreaIsCurcular)
1781                                 {
1782                                         // Adjust area to fit the axis title
1783                                         float   xTitleSize = (float)Math.Max(this.AxisY.titleSize, this.AxisY2.titleSize);
1784                                         if(xTitleSize > 0)
1785                                         {
1786                                                 plottingRect.X += xTitleSize;
1787                                                 plottingRect.Width -= 2f * xTitleSize;
1788                                         }
1789                                         float   yTitleSize = (float)Math.Max(this.AxisX.titleSize, this.AxisX2.titleSize);
1790                                         if(yTitleSize > 0)
1791                                         {
1792                                                 plottingRect.Y += yTitleSize;
1793                                                 plottingRect.Height -= 2f * yTitleSize;
1794                                         }
1795
1796                                         // Make a square plotting rect
1797                                         RectangleF rect = chartGraph.GetAbsoluteRectangle( plottingRect );
1798                                         if(rect.Width > rect.Height)
1799                                         {
1800                                                 rect.X += (rect.Width - rect.Height) / 2f;
1801                                                 rect.Width = rect.Height;
1802                                         }
1803                                         else
1804                                         {
1805                                                 rect.Y += (rect.Height - rect.Width) / 2f;
1806                                                 rect.Height = rect.Width;                                       
1807                                         }
1808                                         plottingRect = chartGraph.GetRelativeRectangle( rect );
1809
1810                                         // Remember circular chart area center
1811                                         this.circularCenter = new PointF(plottingRect.X + plottingRect.Width/2f, plottingRect.Y + plottingRect.Height/2f);
1812
1813                                         // Calculate auto-fit font of the circular axis labels and update area position
1814                                         FitCircularLabels(chartGraph, this.PlotAreaPosition, ref plottingRect, xTitleSize, yTitleSize);
1815                                 }
1816
1817                                 //******************************************************
1818                                 //** Set plotting area position
1819                                 //******************************************************
1820                                 if(plottingRect.Width < 0f)
1821                                 {
1822                                         plottingRect.Width = 0f;
1823                                 }
1824                                 if(plottingRect.Height < 0f)
1825                                 {
1826                                         plottingRect.Height = 0f;
1827                                 }
1828                                 PlotAreaPosition.FromRectangleF(plottingRect);
1829                                 InnerPlotPosition.SetPositionNoAuto(
1830                                         (float)Math.Round((plottingRect.X - Position.X) / (Position.Width / 100F), 5), 
1831                                         (float)Math.Round((plottingRect.Y - Position.Y) / (Position.Height / 100F), 5), 
1832                                         (float)Math.Round(plottingRect.Width / (Position.Width / 100F), 5), 
1833                                         (float)Math.Round(plottingRect.Height / (Position.Height / 100F), 5));
1834
1835
1836                                 //******************************************************
1837                                 //** Adjust label font size for axis, which were 
1838                                 //** automatically calculated after the opposite axis 
1839                                 //** change the size of plotting area.
1840                                 //******************************************************
1841                                 this.AxisY2.AdjustLabelFontAtSecondPass(chartGraph, InnerPlotPosition.Auto);
1842                                 this.AxisY.AdjustLabelFontAtSecondPass(chartGraph, InnerPlotPosition.Auto);
1843                                 if(InnerPlotPosition.Auto)
1844                                 {
1845                                         this.AxisX2.AdjustLabelFontAtSecondPass(chartGraph, InnerPlotPosition.Auto);
1846                                         this.AxisX.AdjustLabelFontAtSecondPass(chartGraph, InnerPlotPosition.Auto);
1847                                 }
1848
1849                         }
1850
1851             /// <summary>
1852             /// Finds axis by it's position. Can be Null.
1853             /// </summary>
1854             /// <param name="axisPosition">Axis position to find</param>
1855             /// <returns>Found axis.</returns>
1856                         private Axis FindAxis(AxisPosition axisPosition)
1857                         {
1858                                 foreach(Axis axis in this.Axes)
1859                                 {
1860                                         if(axis.AxisPosition == axisPosition)
1861                                         {
1862                                                 return axis;
1863                                         }
1864                                 }
1865                                 return null;
1866                         }
1867
1868                         /// <summary>
1869                         /// Shift top/bottom labels so they will not overlap with left/right labels.
1870                         /// </summary>
1871                         /// <param name="axis">Axis to shift up/down.</param>
1872                         private void PreventTopBottomAxesLabelsOverlapping(Axis axis)
1873                         {
1874                                 // If axis is not on the edge of the chart area do not
1875                                 // try to adjust it's position when axis labels overlap
1876                                 // labels of the oppositie axis.
1877                                 if( !axis.IsAxisOnAreaEdge )
1878                                 {
1879                                         return;
1880                                 }
1881
1882                                 // Shift bottom axis labels down
1883                                 if(axis.AxisPosition == AxisPosition.Bottom)
1884                                 {
1885                                         // Get labels position
1886                                         float labelsPosition = (float)axis.GetAxisPosition();
1887                                         if( !axis.GetIsMarksNextToAxis() )
1888                                         {
1889                                                 labelsPosition = axis.PlotAreaPosition.Bottom;
1890                                         }
1891
1892                                         // Only adjust labels outside plotting area
1893                                         if(Math.Round(labelsPosition, 2) < Math.Round(axis.PlotAreaPosition.Bottom, 2))
1894                                         {
1895                                                 return;
1896                                         }
1897
1898                                         // Check if labels may overlap with Left axis
1899                                         Axis    leftAxis = FindAxis(AxisPosition.Left);
1900                                         if(leftAxis != null && 
1901                         leftAxis.enabled &&
1902                                                 leftAxis.labelFarOffset != 0 &&
1903                                                 leftAxis.labelFarOffset > labelsPosition &&
1904                                                 axis.labelNearOffset != 0 && 
1905                                                 axis.labelNearOffset < PlotAreaPosition.X)
1906                                         {
1907                                                 float overlap = (float)(leftAxis.labelFarOffset - labelsPosition) * 0.75f;
1908                                                 if(overlap > axis.markSize)
1909                                                 {
1910                                                         axis.markSize += overlap - axis.markSize;
1911                                                 }
1912                                         }
1913
1914                                         // Check if labels may overlap with Right axis
1915                                         Axis    rightAxis = FindAxis(AxisPosition.Right);
1916                                         if(rightAxis != null &&
1917                         rightAxis.enabled &&
1918                                                 rightAxis.labelFarOffset != 0 &&
1919                                                 rightAxis.labelFarOffset > labelsPosition &&
1920                                                 axis.labelFarOffset != 0 && 
1921                                                 axis.labelFarOffset > PlotAreaPosition.Right)
1922                                         {
1923                                                 float overlap = (float)(rightAxis.labelFarOffset - labelsPosition) * 0.75f;
1924                                                 if(overlap > axis.markSize)
1925                                                 {
1926                                                         axis.markSize += overlap - axis.markSize;
1927                                                 }
1928                                         }
1929                                 }
1930
1931                                         // Shift top axis labels up
1932                                 else if(axis.AxisPosition == AxisPosition.Top)
1933                                 {
1934                                         // Get labels position
1935                                         float labelsPosition = (float)axis.GetAxisPosition();
1936                                         if( !axis.GetIsMarksNextToAxis() )
1937                                         {
1938                                                 labelsPosition = axis.PlotAreaPosition.Y;
1939                                         }
1940
1941                                         // Only adjust labels outside plotting area
1942                                         if(Math.Round(labelsPosition, 2) < Math.Round(axis.PlotAreaPosition.Y, 2))
1943                                         {
1944                                                 return;
1945                                         }
1946
1947                                         // Check if labels may overlap with Left axis
1948                                         Axis    leftAxis = FindAxis(AxisPosition.Left);
1949                                         if(leftAxis != null &&
1950                         leftAxis.enabled &&
1951                                                 leftAxis.labelNearOffset != 0 &&
1952                                                 leftAxis.labelNearOffset < labelsPosition &&
1953                                                 axis.labelNearOffset != 0 && 
1954                                                 axis.labelNearOffset < PlotAreaPosition.X)
1955                                         {
1956                                                 float overlap = (float)(labelsPosition - leftAxis.labelNearOffset) * 0.75f;
1957                                                 if(overlap > axis.markSize)
1958                                                 {
1959                                                         axis.markSize += overlap - axis.markSize;
1960                                                 }
1961                                         }
1962
1963                                         // Check if labels may overlap with Right axis
1964                                         Axis    rightAxis = FindAxis(AxisPosition.Right);
1965                                         if(rightAxis != null &&
1966                         rightAxis.enabled &&
1967                                                 rightAxis.labelNearOffset != 0 &&
1968                                                 rightAxis.labelNearOffset < labelsPosition &&
1969                                                 axis.labelFarOffset != 0 && 
1970                                                 axis.labelFarOffset > PlotAreaPosition.Right)
1971                                         {
1972                                                 float overlap = (float)(labelsPosition - rightAxis.labelNearOffset) * 0.75f;
1973                                                 if(overlap > axis.markSize)
1974                                                 {
1975                                                         axis.markSize += overlap - axis.markSize;
1976                                                 }
1977                                         }
1978                                 }
1979
1980                         }
1981
1982                     #endregion
1983
1984                     #region Painting and Selection Methods
1985
1986                         /// <summary>
1987                         /// Draws chart area background and/or border.
1988                         /// </summary>
1989                         /// <param name="graph">Chart graphics.</param>
1990                         /// <param name="position">Background position.</param>
1991                         /// <param name="borderOnly">Draws chart area border only.</param>
1992                         private void PaintAreaBack(ChartGraphics graph, RectangleF position, bool borderOnly)
1993                         {
1994                                 if(!borderOnly)
1995                                 {
1996                                         // Draw background
1997                                         if(!this.Area3DStyle.Enable3D || !requireAxes || chartAreaIsCurcular)
1998                                         {
1999                                                 // 3D Pie Chart doesn't need scene
2000                                                 // Draw 2D background
2001                                                 graph.FillRectangleRel( 
2002                                                         position, 
2003                                                         BackColor, 
2004                                                         BackHatchStyle, 
2005                                                         BackImage, 
2006                                                         BackImageWrapMode,                              
2007                                                         BackImageTransparentColor,
2008                                                         BackImageAlignment,
2009                                                         BackGradientStyle, 
2010                                                         BackSecondaryColor, 
2011                                                         (requireAxes) ? Color.Empty : BorderColor, 
2012                                                         (requireAxes) ? 0 : BorderWidth, 
2013                                                         BorderDashStyle, 
2014                                                         ShadowColor, 
2015                                                         ShadowOffset, 
2016                                                         PenAlignment.Outset,
2017                                                         chartAreaIsCurcular,
2018                                                         (chartAreaIsCurcular && this.CircularUsePolygons) ? this.CircularSectorsNumber : 0,
2019                                                         this.Area3DStyle.Enable3D);
2020                                         }
2021                                         else
2022                                         {
2023                                                 // Draw chart area 3D scene
2024                                                 this.DrawArea3DScene(graph, position);
2025                                         }
2026                                 }
2027                                 else
2028                                 {
2029                                         if(!this.Area3DStyle.Enable3D || !requireAxes || chartAreaIsCurcular)
2030                                         {
2031                                                 // Draw chart area border
2032                                                 if(BorderColor != Color.Empty && BorderWidth > 0)
2033                                                 {
2034                                                         graph.FillRectangleRel( position, 
2035                                                                 Color.Transparent, 
2036                                                                 ChartHatchStyle.None, 
2037                                                                 "", 
2038                                                                 ChartImageWrapMode.Tile,                                
2039                                                                 Color.Empty,
2040                                                                 ChartImageAlignmentStyle.Center,
2041                                                                 GradientStyle.None, 
2042                                                                 Color.Empty, 
2043                                                                 BorderColor, 
2044                                                                 BorderWidth, 
2045                                                                 BorderDashStyle, 
2046                                                                 Color.Empty, 
2047                                                                 0, 
2048                                                                 PenAlignment.Outset,
2049                                                                 chartAreaIsCurcular,
2050                                                                 (chartAreaIsCurcular && this.CircularUsePolygons) ? this.CircularSectorsNumber : 0,
2051                                                                 this.Area3DStyle.Enable3D);
2052                                                 }
2053                                         }
2054
2055                                 }
2056                         }
2057
2058                         /// <summary>
2059                         /// Paint the chart area.
2060                         /// </summary>
2061                         /// <param name="graph">Chart graphics.</param>
2062                         internal void Paint( ChartGraphics graph )
2063                         {
2064                     // Check if plot area position was recalculated.
2065                     // If not and non-auto InnerPlotPosition & Position were
2066                     // specified - do all needed calculations
2067                     if (PlotAreaPosition.Width == 0 &&
2068                         PlotAreaPosition.Height == 0 &&
2069                         !InnerPlotPosition.Auto
2070                         && !Position.Auto)
2071                     {
2072                         // Initialize plotting area position
2073                         RectangleF plottingRect = Position.ToRectangleF();
2074                         if (!InnerPlotPosition.Auto)
2075                         {
2076                             plottingRect.X += (Position.Width / 100F) * InnerPlotPosition.X;
2077                             plottingRect.Y += (Position.Height / 100F) * InnerPlotPosition.Y;
2078                             plottingRect.Width = (Position.Width / 100F) * InnerPlotPosition.Width;
2079                             plottingRect.Height = (Position.Height / 100F) * InnerPlotPosition.Height;
2080                         }
2081
2082                         PlotAreaPosition.FromRectangleF(plottingRect);
2083                     }
2084
2085                     // Get background position rectangle.
2086                     RectangleF backgroundPositionWithScrollBars = GetBackgroundPosition(true);
2087                     RectangleF backgroundPosition = GetBackgroundPosition(false);
2088
2089                     // Add hot region for plotting area.
2090                     if (Common.ProcessModeRegions)
2091                     {
2092                         Common.HotRegionsList.AddHotRegion(backgroundPosition, this, ChartElementType.PlottingArea, true);
2093                     }
2094                     // Draw background
2095                     PaintAreaBack(graph, backgroundPositionWithScrollBars, false);
2096
2097                     // Call BackPaint event
2098                     Common.Chart.CallOnPrePaint(new ChartPaintEventArgs(this, graph, Common, PlotAreaPosition));
2099
2100                     // Draw chart types without axes - Pie.
2101                     if (!requireAxes && ChartTypes.Count != 0)
2102                     {
2103                         // Find first chart type that do not require axis (like Pie) and draw it.
2104                         // Chart types that do not require axes (circular charts) cannot be combined with
2105                         // any other chart types.
2106                         // NOTE: Fixes issues #4672 and #4692
2107                         for (int chartTypeIndex = 0; chartTypeIndex < ChartTypes.Count; chartTypeIndex++)
2108                         {
2109                             IChartType chartType = Common.ChartTypeRegistry.GetChartType((string)ChartTypes[chartTypeIndex]);
2110                             if (!chartType.RequireAxes)
2111                             {
2112                                 chartType.Paint(graph, Common, this, null);
2113                                 break;
2114                             }
2115                         }
2116
2117                         // Call Paint event
2118                         Common.Chart.CallOnPostPaint(new ChartPaintEventArgs(this, graph, Common, PlotAreaPosition));
2119                         return;
2120                     }
2121
2122
2123
2124                     // Reset Smart Labels 
2125                     this.smartLabels.Reset();
2126
2127
2128
2129                     // Set values for optimized drawing
2130                     foreach (Axis currentAxis in this._axisArray)
2131                     {
2132                         currentAxis.optimizedGetPosition = true;
2133                         currentAxis.paintViewMax = currentAxis.ViewMaximum;
2134                         currentAxis.paintViewMin = currentAxis.ViewMinimum;
2135                         currentAxis.paintRange = currentAxis.paintViewMax - currentAxis.paintViewMin;
2136                         currentAxis.paintAreaPosition = PlotAreaPosition.ToRectangleF();
2137                         if (currentAxis.ChartArea != null && currentAxis.ChartArea.chartAreaIsCurcular)
2138                         {
2139                             // Update position for circular chart area
2140                             currentAxis.paintAreaPosition.Width /= 2.0f;
2141                             currentAxis.paintAreaPosition.Height /= 2.0f;
2142                         }
2143                         currentAxis.paintAreaPositionBottom = currentAxis.paintAreaPosition.Y + currentAxis.paintAreaPosition.Height;
2144                         currentAxis.paintAreaPositionRight = currentAxis.paintAreaPosition.X + currentAxis.paintAreaPosition.Width;
2145                         if (currentAxis.AxisPosition == AxisPosition.Top || currentAxis.AxisPosition == AxisPosition.Bottom)
2146                             currentAxis.paintChartAreaSize = currentAxis.paintAreaPosition.Width;
2147                         else
2148                             currentAxis.paintChartAreaSize = currentAxis.paintAreaPosition.Height;
2149
2150                         currentAxis.valueMultiplier = 0.0;
2151                         if (currentAxis.paintRange != 0)
2152                         {
2153                             currentAxis.valueMultiplier = currentAxis.paintChartAreaSize / currentAxis.paintRange;
2154                         }
2155                     }
2156                     
2157                     // Draw Axis Striplines (only when StripWidth > 0)
2158                     bool useScaleSegments = false;
2159                     Axis[] axesArray = new Axis[] { axisY, axisY2, axisX, axisX2 };
2160                     foreach (Axis currentAxis in axesArray)
2161                     {
2162
2163                         useScaleSegments = (currentAxis.ScaleSegments.Count > 0);
2164
2165                         if (!useScaleSegments)
2166                         {
2167                             currentAxis.PaintStrips(graph, false);
2168                         }
2169
2170                         else
2171                         {
2172                             foreach (AxisScaleSegment scaleSegment in currentAxis.ScaleSegments)
2173                             {
2174                                 scaleSegment.SetTempAxisScaleAndInterval();
2175
2176                                 currentAxis.PaintStrips(graph, false);
2177
2178                                 scaleSegment.RestoreAxisScaleAndInterval();
2179                             }
2180                         }
2181                                         }
2182
2183                     // Draw Axis Grids
2184                     axesArray = new Axis[] { axisY, axisX2, axisY2, axisX };
2185                     foreach (Axis currentAxis in axesArray)
2186                     {
2187
2188                         useScaleSegments = (currentAxis.ScaleSegments.Count > 0);
2189
2190                         if (!useScaleSegments)
2191                         {
2192                             currentAxis.PaintGrids(graph);
2193                         }
2194
2195                         else
2196                         {
2197                             foreach (AxisScaleSegment scaleSegment in currentAxis.ScaleSegments)
2198                             {
2199                                 scaleSegment.SetTempAxisScaleAndInterval();
2200
2201                                 currentAxis.PaintGrids(graph);
2202
2203                                 scaleSegment.RestoreAxisScaleAndInterval();
2204                             }
2205                         }
2206
2207                     }
2208
2209                     // Draw Axis Striplines (only when StripWidth == 0)
2210                     foreach (Axis currentAxis in axesArray)
2211                     {
2212
2213                         useScaleSegments = (currentAxis.ScaleSegments.Count > 0);
2214
2215                         if (!useScaleSegments)
2216                         {
2217                             currentAxis.PaintStrips(graph, true);
2218                         }
2219
2220                         else
2221                         {
2222                             foreach (AxisScaleSegment scaleSegment in currentAxis.ScaleSegments)
2223                             {
2224                                 scaleSegment.SetTempAxisScaleAndInterval();
2225
2226                                 currentAxis.PaintStrips(graph, true);
2227
2228                                 scaleSegment.RestoreAxisScaleAndInterval();
2229                             }
2230                         }
2231
2232                     }
2233
2234                     // Draw Axis elements on the back of the 3D scene
2235                     if (this.Area3DStyle.Enable3D && !this.chartAreaIsCurcular)
2236                     {
2237                         foreach (Axis currentAxis in axesArray)
2238                         {
2239
2240                             useScaleSegments = (currentAxis.ScaleSegments.Count > 0);
2241
2242                             if (!useScaleSegments)
2243                             {
2244                                 currentAxis.PrePaint(graph);
2245                             }
2246
2247                             else
2248                             {
2249                                 foreach (AxisScaleSegment scaleSegment in currentAxis.ScaleSegments)
2250                                 {
2251                                     scaleSegment.SetTempAxisScaleAndInterval();
2252
2253                                     currentAxis.PrePaint(graph);
2254
2255                                     scaleSegment.RestoreAxisScaleAndInterval();
2256                                 }
2257
2258                             }
2259
2260                         }
2261                     }
2262
2263                     // Draws chart area border
2264                     bool borderDrawn = false;
2265                     if (this.Area3DStyle.Enable3D || !IsBorderOnTopSeries())
2266                     {
2267                         borderDrawn = true;
2268                         PaintAreaBack(graph, backgroundPosition, true);
2269                     }
2270
2271                     // Draw chart types
2272                     if (!this.Area3DStyle.Enable3D || this.chartAreaIsCurcular)
2273                     {
2274                         // Drawing in 2D space
2275
2276                         // NOTE: Fixes issue #6443 and #5385
2277                         // If two chart series of the same type (for example Line) are separated
2278                         // by other series (for example Area) the order is not correct.
2279                         // Old implementation draws ALL series that belongs to the chart type.
2280                         ArrayList typeAndSeries = this.GetChartTypesAndSeriesToDraw(); 
2281                         
2282                         // Draw series by chart type or by series
2283                         foreach (ChartTypeAndSeriesInfo chartTypeInfo in typeAndSeries)
2284                         {
2285                             this.IterationCounter = 0;
2286                             IChartType type = Common.ChartTypeRegistry.GetChartType(chartTypeInfo.ChartType);
2287
2288                             // If 'chartTypeInfo.Series' set to NULL all series of that chart type are drawn at once
2289                             type.Paint(graph, Common, this, chartTypeInfo.Series);
2290                         }
2291                     }
2292                     else
2293                     {
2294                         // Drawing in 3D space
2295                         PaintChartSeries3D(graph);
2296                     }
2297
2298                     // Draw area border if it wasn't drawn prior to the series
2299                     if (!borderDrawn)
2300                     {
2301                         PaintAreaBack(graph, backgroundPosition, true);
2302                     }
2303
2304                     // Draw Axis
2305                     foreach (Axis currentAxis in axesArray)
2306                     {
2307
2308                         useScaleSegments = (currentAxis.ScaleSegments.Count > 0);
2309
2310                         if (!useScaleSegments)
2311                         {
2312                             // Paint axis and Reset temp axis offset for side-by-side charts like column
2313                             currentAxis.Paint(graph);
2314                         }
2315
2316                         else
2317                         {
2318                             // Some of the axis elements like grid lines and tickmarks 
2319                             // are drawn for each segment
2320                             foreach (AxisScaleSegment scaleSegment in currentAxis.ScaleSegments)
2321                             {
2322                                 scaleSegment.SetTempAxisScaleAndInterval();
2323
2324                                 currentAxis.PaintOnSegmentedScalePassOne(graph);
2325
2326                                 scaleSegment.RestoreAxisScaleAndInterval();
2327                             }
2328
2329                             // Other elements like labels, title, axis line are drawn once
2330                             currentAxis.PaintOnSegmentedScalePassTwo(graph);
2331                         }
2332
2333                     }
2334
2335                     // Call Paint event
2336                     Common.Chart.CallOnPostPaint(new ChartPaintEventArgs(this, graph, Common, PlotAreaPosition));
2337
2338                     // Draw axis scale break lines
2339                     axesArray = new Axis[] { axisY, axisY2 };
2340                     foreach (Axis currentAxis in axesArray)
2341                     {
2342                         for (int segmentIndex = 0; segmentIndex < (currentAxis.ScaleSegments.Count - 1); segmentIndex++)
2343                         {
2344                             currentAxis.ScaleSegments[segmentIndex].PaintBreakLine(graph, currentAxis.ScaleSegments[segmentIndex + 1]);
2345
2346                         }
2347                     }
2348
2349                     // Reset values for optimized drawing
2350                     foreach (Axis curentAxis in this._axisArray)
2351                     {
2352                         curentAxis.optimizedGetPosition = false;
2353
2354
2355                         // Reset preffered number of intervals on the axis
2356                         curentAxis.prefferedNumberofIntervals = 5;
2357
2358                         // Reset flag that scale segments are used
2359                         curentAxis.scaleSegmentsUsed = false;
2360
2361
2362                     }
2363                 }
2364
2365                 /// <summary>
2366                 /// Checks if chart area border should be drawn on top of series.
2367                 /// </summary>
2368                 /// <returns>True if border should be darwn on top.</returns>
2369                 private bool IsBorderOnTopSeries()
2370                 {
2371                         // For most of the chart types chart area border is drawn on top.
2372                         bool result = true;
2373                         foreach( Series series in this.Common.Chart.Series )
2374                         {
2375                                 if(series.ChartArea == this.Name)
2376                                 {
2377                                         // It is common for the Bubble and Point chart types to draw markers
2378                                         // partially outside of the chart area. By drawing the border before
2379                                         // series we avoiding the possibility of drawing the border line on 
2380                                         // top of the marker.
2381                                         if(series.ChartType == SeriesChartType.Bubble || 
2382                                                 series.ChartType == SeriesChartType.Point)
2383                                         {
2384                                                 return false;
2385                                         }
2386                                 }
2387                         }
2388                         return result;
2389                 }
2390
2391                 /// <summary>
2392                 /// Paint the chart area cursors.
2393                 /// </summary>
2394                 /// <param name="graph">Chart graphics.</param>
2395                 /// <param name="cursorOnly">Indicates that only cursors are redrawn.</param>
2396         [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", Justification = "These parameters are used when compiling for the Microsoft version of Chart")]
2397                 internal void PaintCursors( ChartGraphics graph, bool cursorOnly )
2398                 {
2399                         // Cursors and selection are supoorted only in 2D charts
2400                         if(this.Area3DStyle.Enable3D == true)
2401                         {
2402                                 return;
2403                         }
2404
2405                         // Do not draw cursor/selection for chart types that do not require axis (like Pie)
2406                         if(!this.requireAxes)
2407                         {
2408                                 return;
2409                         }
2410
2411                         // Cursors and selection are not supoorted in circular areas
2412                         if(this.chartAreaIsCurcular)
2413                         {
2414                                 return;
2415                         }
2416
2417                         // Do not draw cursor/selection while printing
2418                         if(this.Common != null && 
2419                                 this.Common.ChartPicture != null && 
2420                                 this.Common.ChartPicture.isPrinting)
2421                         {
2422                                 return;
2423                         }
2424
2425                         // Do not draw cursor/selection when chart area is not visible
2426                         // because either width or height is set to zero
2427                         if(this.Position.Width == 0f ||
2428                                 this.Position.Height == 0f)
2429                         {
2430                                 return;
2431             }
2432
2433 #if Microsoft_CONTROL
2434
2435             Chart chart = this.Common.Chart;
2436             ChartPicture chartPicture = Common.ChartPicture;
2437
2438                         // Check if cursor should be drawn
2439                         if(!double.IsNaN(_cursorX.SelectionStart) ||
2440                                 !double.IsNaN(_cursorX.SelectionEnd) ||
2441                                 !double.IsNaN(_cursorX.Position) ||
2442                                 !double.IsNaN(_cursorY.SelectionStart) ||
2443                                 !double.IsNaN(_cursorY.SelectionEnd) ||
2444                                 !double.IsNaN(_cursorY.Position))
2445                         {
2446
2447                                 if(!chartPicture.backgroundRestored &&
2448                                         !chartPicture.isSelectionMode )
2449                                 {
2450                                         chartPicture.backgroundRestored = true;
2451
2452                                         Rectangle chartPosition = new Rectangle(0, 0, chartPicture.Width, chartPicture.Height);
2453
2454                                         // Get chart area position
2455                                         Rectangle absAreaPlotPosition = Rectangle.Round(graph.GetAbsoluteRectangle(PlotAreaPosition.ToRectangleF()));
2456                                         int maxCursorWidth = (CursorY.LineWidth > CursorX.LineWidth) ? CursorY.LineWidth + 1 : CursorX.LineWidth + 1;
2457                                         absAreaPlotPosition.Inflate(maxCursorWidth, maxCursorWidth);
2458                                         absAreaPlotPosition.Intersect(new Rectangle(0, 0, chart.Width, chart.Height));
2459
2460                                         // Create area buffer bitmap
2461                                         if(areaBufferBitmap == null || 
2462                                                 chartPicture.nonTopLevelChartBuffer == null ||
2463                                                 !cursorOnly)
2464                                         {
2465                                                 // Dispose previous bitmap
2466                                                 if(areaBufferBitmap != null)
2467                                                 {
2468                                                         areaBufferBitmap.Dispose();
2469                                                         areaBufferBitmap = null;
2470                                                 }
2471                                                 if(chartPicture.nonTopLevelChartBuffer != null)
2472                                                 {
2473                                                         chartPicture.nonTopLevelChartBuffer.Dispose();
2474                                                         chartPicture.nonTopLevelChartBuffer = null;
2475                                                 }
2476
2477
2478                                                 // Copy chart area plotting rectangle from the chart's dubble buffer image into area dubble buffer image
2479                                                 if(chart.paintBufferBitmap != null)
2480                                                 {
2481                                                         areaBufferBitmap = chart.paintBufferBitmap.Clone(absAreaPlotPosition, chart.paintBufferBitmap.PixelFormat);
2482                                                 }
2483
2484                                                 // Copy whole chart from the chart's dubble buffer image into area dubble buffer image
2485                                                 if(chart.paintBufferBitmap != null && 
2486                                                         chart.paintBufferBitmap.Size.Width >= chartPosition.Size.Width &&
2487                                                         chart.paintBufferBitmap.Size.Height >= chartPosition.Size.Height)
2488                                                 {
2489                                                         chartPicture.nonTopLevelChartBuffer = chart.paintBufferBitmap.Clone(
2490                                                                 chartPosition, chart.paintBufferBitmap.PixelFormat);
2491                                                 }
2492
2493                                         }
2494                                         else if(cursorOnly && chartPicture.nonTopLevelChartBuffer != null)
2495                                         {
2496                                                 // Restore previous background
2497                                                 chart.paintBufferBitmapGraphics.DrawImageUnscaled(
2498                                                         chartPicture.nonTopLevelChartBuffer,
2499                                                         chartPosition);
2500                                         }
2501                                 }
2502
2503                 // Draw chart area cursors and range selection
2504
2505                                 _cursorY.Paint(graph);
2506                                 _cursorX.Paint(graph);
2507
2508             }
2509 #endif // Microsoft_CONTROL
2510
2511         }
2512
2513                 #endregion
2514
2515                     #region Circular chart area methods
2516
2517         /// <summary>
2518         /// Gets a circular chart type interface that belongs to this chart area.
2519         /// </summary>
2520         /// <returns>ICircularChartType interface or null.</returns>
2521                 internal ICircularChartType GetCircularChartType()
2522                 {
2523                         // Get number of sectors in circular chart area
2524                         foreach(Series series in this.Common.DataManager.Series)
2525                         {
2526                                 if(series.IsVisible() && series.ChartArea == this.Name)
2527                                 {
2528                                         ICircularChartType type = Common.ChartTypeRegistry.GetChartType(series.ChartTypeName) as ICircularChartType;;
2529                                         if(type != null)
2530                                         {
2531                                                 return type;
2532                                         }
2533                                 }
2534                         }
2535                         return null;
2536                 }
2537
2538                 /// <summary>
2539                 /// Calculate size of the circular axis labels and sets auto-fit font.
2540                 /// </summary>
2541                 /// <param name="chartGraph">Chart graphics object.</param>
2542                 /// <param name="chartAreaPosition">The Chart area position.</param>
2543                 /// <param name="plotArea">Plotting area size.</param>
2544                 /// <param name="xTitleSize">Size of title on the axis.</param>
2545                 /// <param name="yTitleSize">Size of title on the axis.</param>
2546                 internal void FitCircularLabels(
2547                         ChartGraphics chartGraph, 
2548                         ElementPosition chartAreaPosition, 
2549                         ref RectangleF plotArea,
2550                         float xTitleSize,
2551                         float yTitleSize)
2552                 {
2553                         // Check if axis labels are enabled
2554                         if(!this.AxisX.LabelStyle.Enabled)
2555                         {
2556                                 return;
2557                         }
2558
2559                         // Get absolute titles size
2560                         SizeF   titleSize = chartGraph.GetAbsoluteSize(new SizeF(xTitleSize, yTitleSize));
2561
2562                         // Get absolute position of area
2563                         RectangleF plotAreaRectAbs = chartGraph.GetAbsoluteRectangle( plotArea );
2564                         RectangleF areaRectAbs = chartGraph.GetAbsoluteRectangle( chartAreaPosition.ToRectangleF());
2565
2566                         // Get absolute markers size and spacing
2567                         float   spacing = chartGraph.GetAbsolutePoint(new PointF(0, this.AxisX.markSize + Axis.elementSpacing)).Y;
2568
2569                         // Get circular axis list
2570                         ArrayList axisList = GetCircularAxisList();
2571
2572                         // Get circular axis labels style
2573                         CircularAxisLabelsStyle labelsStyle = GetCircularAxisLabelsStyle();
2574
2575                         //*****************************************************************
2576                         //** Calculate the auto-fit font if required
2577                         //*****************************************************************
2578                         if(this.AxisX.LabelStyle.Enabled && this.AxisX.IsLabelAutoFit)
2579                         {
2580                                 // Set max auto fit font
2581                                 this.AxisX.autoLabelFont = Common.ChartPicture.FontCache.GetFont(
2582                     this.AxisX.LabelStyle.Font.FontFamily, 
2583                                         14, 
2584                                         this.AxisX.LabelStyle.Font.Style, 
2585                                         GraphicsUnit.Point);
2586
2587                                 // Get estimated labels size
2588                                 float labelsSizeEstimate = GetCircularLabelsSize(chartGraph, areaRectAbs, plotAreaRectAbs, titleSize);
2589                                 labelsSizeEstimate = (float)Math.Min(labelsSizeEstimate * 1.1f, plotAreaRectAbs.Width / 5f);
2590                                 labelsSizeEstimate += spacing;
2591
2592                                 // Calculate auto-fit font
2593                                 this.AxisX.GetCircularAxisLabelsAutoFitFont(chartGraph, axisList, labelsStyle, plotAreaRectAbs, areaRectAbs, labelsSizeEstimate);
2594                         }
2595
2596                         //*****************************************************************
2597                         //** Shrink plot area size proportionally
2598                         //*****************************************************************
2599
2600                         // Get labels size
2601                         float labelsSize = GetCircularLabelsSize(chartGraph, areaRectAbs, plotAreaRectAbs, titleSize);
2602
2603                         // Check if change size is smaller than radius
2604                         labelsSize = (float)Math.Min(labelsSize, plotAreaRectAbs.Width / 2.5f);
2605                         labelsSize += spacing;
2606                         
2607                         plotAreaRectAbs.X += labelsSize;
2608                         plotAreaRectAbs.Width -= 2f * labelsSize;
2609                         plotAreaRectAbs.Y += labelsSize;
2610                         plotAreaRectAbs.Height -= 2f * labelsSize;
2611
2612                         // Restrict minimum plot area size
2613                         if(plotAreaRectAbs.Width < 1.0f)
2614                         {
2615                                 plotAreaRectAbs.Width = 1.0f;
2616                         }
2617                         if(plotAreaRectAbs.Height < 1.0f)
2618                         {
2619                                 plotAreaRectAbs.Height = 1.0f;
2620                         }
2621
2622                         plotArea = chartGraph.GetRelativeRectangle( plotAreaRectAbs );
2623                         
2624
2625                         //*****************************************************************
2626                         //** Set axes labels size
2627                         //*****************************************************************
2628                         SizeF   relativeLabelSize = chartGraph.GetRelativeSize(new SizeF(labelsSize, labelsSize));
2629                         this.AxisX.labelSize = relativeLabelSize.Height;
2630                         this.AxisX2.labelSize = relativeLabelSize.Height;
2631                         this.AxisY.labelSize = relativeLabelSize.Width;
2632                         this.AxisY2.labelSize = relativeLabelSize.Width;
2633
2634                 }
2635
2636                 /// <summary>
2637                 /// Calculate size of the circular axis labels.
2638                 /// </summary>
2639                 /// <param name="chartGraph">Chart graphics object.</param>
2640                 /// <param name="areaRectAbs">The Chart area position.</param>
2641                 /// <param name="plotAreaRectAbs">Plotting area size.</param>
2642                 /// <param name="titleSize">Size of title on the axes.</param>
2643                 /// <returns>Circulat labels style.</returns>
2644                 internal float GetCircularLabelsSize(
2645                         ChartGraphics chartGraph, 
2646                         RectangleF areaRectAbs, 
2647                         RectangleF plotAreaRectAbs,
2648                         SizeF titleSize)
2649                 {
2650                         // Find current horiz. and vert. spacing between plotting and chart areas
2651                         SizeF   areaDiff = new SizeF(plotAreaRectAbs.X - areaRectAbs.X, plotAreaRectAbs.Y - areaRectAbs.Y);
2652                         areaDiff.Width -= titleSize.Width;
2653                         areaDiff.Height -= titleSize.Height;
2654
2655                         // Get absolute center of the area
2656                         PointF  areaCenterAbs = chartGraph.GetAbsolutePoint(this.circularCenter);
2657
2658                         // Get circular axis list
2659                         ArrayList axisList = GetCircularAxisList();
2660
2661                         // Get circular axis labels style
2662                         CircularAxisLabelsStyle labelsStyle = GetCircularAxisLabelsStyle();
2663
2664                         // Defines on how much (pixels) the circular chart area radius should be reduced
2665                         float   labelsSize = 0f;
2666
2667                         //*****************************************************************
2668                         //** Loop through all axis labels
2669                         //*****************************************************************
2670                         foreach(CircularChartAreaAxis axis in axisList)
2671                         {
2672                                 //*****************************************************************
2673                                 //** Measure label text
2674                                 //*****************************************************************
2675                                 SizeF   textSize = chartGraph.MeasureString(
2676                                         axis.Title.Replace("\\n", "\n"), 
2677                                         (this.AxisX.autoLabelFont == null) ? this.AxisX.LabelStyle.Font : this.AxisX.autoLabelFont);
2678                                 textSize.Width = (float)Math.Ceiling(textSize.Width * 1.1f);
2679                                 textSize.Height = (float)Math.Ceiling(textSize.Height * 1.1f);
2680
2681
2682                                 //*****************************************************************
2683                                 //** Calculate area size change depending on labels style
2684                                 //*****************************************************************
2685                                 if(labelsStyle == CircularAxisLabelsStyle.Circular)
2686                                 {
2687                                         labelsSize = (float)Math.Max(
2688                                                 labelsSize, 
2689                                                 textSize.Height);
2690                                 }
2691                                 else if(labelsStyle == CircularAxisLabelsStyle.Radial)
2692                                 {
2693                                         float textAngle = axis.AxisPosition + 90;
2694
2695                                         // For angled text find it's X and Y components
2696                                         float   width = (float)Math.Cos(textAngle/180F*Math.PI) * textSize.Width;
2697                                         float   height = (float)Math.Sin(textAngle/180F*Math.PI) * textSize.Width;
2698                                         width = (float)Math.Abs(Math.Ceiling(width));
2699                                         height = (float)Math.Abs(Math.Ceiling(height));
2700
2701                                         // Reduce text size by current spacing between plotting area and chart area
2702                                         width -= areaDiff.Width;
2703                                         height -= areaDiff.Height;
2704                                         if(width < 0)
2705                                                 width = 0;
2706                                         if(height < 0)
2707                                                 height = 0;
2708
2709
2710                                         labelsSize = (float)Math.Max(
2711                                                 labelsSize, 
2712                                                 Math.Max(width, height));
2713                                 }
2714                                 else if(labelsStyle == CircularAxisLabelsStyle.Horizontal)
2715                                 {
2716                                         // Get text angle
2717                                         float textAngle = axis.AxisPosition;
2718                                         if(textAngle > 180f)
2719                                         {
2720                                                 textAngle -= 180f;
2721                                         }
2722
2723                                         // Get label rotated position
2724                                         PointF[]        labelPosition = new PointF[] { new PointF(areaCenterAbs.X, plotAreaRectAbs.Y) };
2725                                         Matrix newMatrix = new Matrix();
2726                                         newMatrix.RotateAt(textAngle, areaCenterAbs);
2727                                         newMatrix.TransformPoints(labelPosition);
2728
2729                                         // Calculate width
2730                                         float width = textSize.Width;
2731                                         width -= areaRectAbs.Right - labelPosition[0].X;
2732                                         if(width < 0f)
2733                                         {
2734                                                 width = 0f;
2735                                         }
2736
2737                                         labelsSize = (float)Math.Max(
2738                                                 labelsSize, 
2739                                                 Math.Max(width, textSize.Height));
2740                                 }
2741                         }
2742
2743                         return labelsSize;
2744                 }
2745
2746                 /// <summary>
2747                 /// True if polygons should be used instead of the circles for the chart area.
2748                 /// </summary>
2749                 internal bool CircularUsePolygons
2750                 {
2751                         get
2752                         {
2753                                 // Check if value was precalculated
2754                                 if(this._circularUsePolygons == int.MinValue)
2755                                 {
2756                                         _circularUsePolygons = 0;
2757
2758                                         // Look for custom properties in series
2759                                         foreach(Series series in this.Common.DataManager.Series)
2760                                         {
2761                                                 if(series.ChartArea == this.Name && series.IsVisible())
2762                                                 {
2763                                                         // Get custom attribute
2764                             if (series.IsCustomPropertySet(CustomPropertyName.AreaDrawingStyle))
2765                                                         {
2766                                                                 if(String.Compare(series[CustomPropertyName.AreaDrawingStyle], "Polygon", StringComparison.OrdinalIgnoreCase) == 0)
2767                                                                 {
2768                                                                         _circularUsePolygons = 1;
2769                                                                 }
2770                                 else if (String.Compare(series[CustomPropertyName.AreaDrawingStyle], "Circle", StringComparison.OrdinalIgnoreCase) == 0)
2771                                                                 {
2772                                                                         _circularUsePolygons = 0;
2773                                                                 }
2774                                                                 else
2775                                                                 {
2776                                                                         throw(new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid( series[CustomPropertyName.AreaDrawingStyle], "AreaDrawingStyle")));
2777                                                                 }
2778                                                                 break;
2779                                                         }
2780                                                 }
2781                                         }
2782                                 }
2783
2784                                 return (this._circularUsePolygons == 1);
2785                         }
2786                 }
2787
2788                 /// <summary>
2789                 /// Gets circular area axis labels style.
2790                 /// </summary>
2791                 /// <returns>Axis labels style.</returns>
2792                 internal CircularAxisLabelsStyle GetCircularAxisLabelsStyle()
2793                 {
2794                         CircularAxisLabelsStyle style = CircularAxisLabelsStyle.Auto;
2795
2796                         // Get maximum number of points in all series
2797                         foreach(Series series in this.Common.DataManager.Series)
2798                         {
2799                                 if(series.IsVisible() && series.ChartArea == this.Name && series.IsCustomPropertySet(CustomPropertyName.CircularLabelsStyle))
2800                                 {
2801                                         string styleName = series[CustomPropertyName.CircularLabelsStyle];
2802                                         if(String.Compare( styleName, "Auto", StringComparison.OrdinalIgnoreCase) == 0 )
2803                                         {
2804                                                 style = CircularAxisLabelsStyle.Auto;
2805                                         }
2806                                         else if(String.Compare( styleName,"Circular", StringComparison.OrdinalIgnoreCase) == 0)
2807                                         {
2808                                                 style = CircularAxisLabelsStyle.Circular;
2809                                         }
2810                                         else if(String.Compare( styleName,"Radial", StringComparison.OrdinalIgnoreCase) == 0)
2811                                         {
2812                                                 style = CircularAxisLabelsStyle.Radial;
2813                                         }
2814                     else if (String.Compare(styleName, "Horizontal", StringComparison.OrdinalIgnoreCase) == 0)
2815                                         {
2816                                                 style = CircularAxisLabelsStyle.Horizontal;
2817                                         }
2818                                         else
2819                                         {
2820                                                 throw(new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid( styleName, "CircularLabelsStyle")));
2821                                         }
2822                                         
2823                                 }
2824                         }
2825
2826                         // Get auto style
2827                         if(style == CircularAxisLabelsStyle.Auto)
2828                         {
2829                                 int     sectorNumber = CircularSectorsNumber;
2830                                 style = CircularAxisLabelsStyle.Horizontal;
2831                                 if(sectorNumber > 30)
2832                                 {
2833                                         style = CircularAxisLabelsStyle.Radial;
2834                                 }
2835                         }
2836
2837                         return style;
2838                 }
2839
2840                 /// <summary>
2841                 /// Number of sectors in the circular area.
2842                 /// </summary>
2843                 internal int CircularSectorsNumber
2844                 {
2845                         get
2846                         {
2847                                 // Check if value was precalculated
2848                                 if(this._circularSectorNumber == int.MinValue)
2849                                 {
2850                                         this._circularSectorNumber = GetCircularSectorNumber();
2851                                 }
2852
2853                                 return this._circularSectorNumber;
2854                         }
2855                 }
2856
2857                 /// <summary>
2858                 /// Gets number of sectors in the circular chart area.
2859                 /// </summary>
2860                 /// <returns>Number of sectors.</returns>
2861                 private int GetCircularSectorNumber()
2862                 {
2863                         ICircularChartType type = this.GetCircularChartType();
2864                         if(type != null)
2865                         {
2866                                 return type.GetNumerOfSectors(this, this.Common.DataManager.Series);
2867                         }
2868                         return 0;
2869                 }
2870
2871                 /// <summary>
2872                 /// Fills a list of circular axis.
2873                 /// </summary>
2874                 /// <returns>Axes list.</returns>
2875                 internal ArrayList GetCircularAxisList()
2876                 {
2877                         // Check if list was already created
2878                         if(_circularAxisList == null)
2879                         {
2880                                 _circularAxisList = new ArrayList();
2881
2882                                 // Loop through all sectors
2883                                 int sectorNumber = GetCircularSectorNumber();
2884                                 for(int sectorIndex = 0; sectorIndex < sectorNumber; sectorIndex++)
2885                                 {
2886                                         // Create new axis object
2887                                         CircularChartAreaAxis   axis = new CircularChartAreaAxis(sectorIndex * 360f/sectorNumber);
2888
2889                                         // Check if custom X axis labels will be used
2890                                         if(this.AxisX.CustomLabels.Count > 0)
2891                                         {
2892                                                 if(sectorIndex < this.AxisX.CustomLabels.Count)
2893                                                 {
2894                                                         axis.Title = this.AxisX.CustomLabels[sectorIndex].Text;
2895                             axis.TitleForeColor = this.AxisX.CustomLabels[sectorIndex].ForeColor;
2896                                                 }
2897                                         }
2898                                         else
2899                                         {
2900                                                 // Get axis title from all series
2901                                                 foreach(Series series in this.Common.DataManager.Series)
2902                                                 {
2903                                                         if(series.IsVisible() && series.ChartArea == this.Name && sectorIndex < series.Points.Count)
2904                                                         {
2905                                                                 if(series.Points[sectorIndex].AxisLabel.Length > 0)
2906                                                                 {
2907                                                                         axis.Title = series.Points[sectorIndex].AxisLabel;
2908                                                                         break;
2909                                                                 }
2910                                                         }
2911                                                 }
2912                                         }
2913
2914                                         // Add axis into the list
2915                                         _circularAxisList.Add(axis);
2916                                 }
2917
2918                         }
2919                         return _circularAxisList;
2920                 }
2921
2922                 /// <summary>
2923                 /// Converts circular position of the X axis to angle in degrees.
2924                 /// </summary>
2925                 /// <param name="position">X axis position.</param>
2926                 /// <returns>Angle in degrees.</returns>
2927                 internal float CircularPositionToAngle(double position)
2928                 {
2929                         // Get X axis scale size
2930                         double scaleRatio = 360.0 / Math.Abs(this.AxisX.Maximum - this.AxisX.Minimum);
2931                         
2932                         return (float)(position * scaleRatio + this.AxisX.Crossing);
2933                 }
2934
2935                 #endregion
2936
2937             #region 2D Series drawing order methods
2938
2939             /// <summary>
2940             /// Helper method that returns a list of 'ChartTypeAndSeriesInfo' objects.
2941             /// This list is used for chart area series drawing in 2D mode. Each
2942             /// object may represent an individual series or all series that belong
2943             /// to one chart type.
2944             /// 
2945             /// This method is intended to fix issues #6443 and #5385 when area chart 
2946             /// type incorrectly overlaps point or line chart type.
2947             /// </summary>
2948             /// <returns>List of 'ChartTypeAndSeriesInfo' objects.</returns>
2949             private ArrayList GetChartTypesAndSeriesToDraw()
2950             {
2951                 ArrayList resultList = new ArrayList();
2952
2953                 // Build chart type or series position based lists
2954                 if (this.ChartTypes.Count > 1 &&
2955                     (this.ChartTypes.Contains(ChartTypeNames.Area) 
2956                     || this.ChartTypes.Contains(ChartTypeNames.SplineArea)
2957                     )
2958                     )
2959                 {
2960                     // Array of chart type names that do not require furher processing
2961                     ArrayList processedChartType = new ArrayList();
2962                     ArrayList splitChartType = new ArrayList();
2963
2964                     // Draw using the exact order in the series collection
2965                     int seriesIndex = 0;
2966                     foreach (Series series in this.Common.DataManager.Series)
2967                     {
2968                         // Check if series is visible and belongs to the chart area
2969                         if (series.ChartArea==this.Name && series.IsVisible() && series.Points.Count > 0)
2970                         {
2971                             // Check if this chart type was already processed
2972                             if (!processedChartType.Contains(series.ChartTypeName))
2973                             {
2974                                 // Check if curent chart type can be individually processed
2975                                 bool canBeIndividuallyProcessed = false;
2976                                 if (series.ChartType == SeriesChartType.Point ||
2977                                     series.ChartType == SeriesChartType.Line ||
2978                                     series.ChartType == SeriesChartType.Spline ||
2979                                     series.ChartType == SeriesChartType.StepLine)
2980                                 {
2981                                     canBeIndividuallyProcessed = true;
2982                                 }
2983
2984                                 if (!canBeIndividuallyProcessed)
2985                                 {
2986                                     // Add a record to process all series of that chart type at once
2987                                     resultList.Add(new ChartTypeAndSeriesInfo(series.ChartTypeName));
2988                                     processedChartType.Add(series.ChartTypeName);
2989                                 }
2990                                 else
2991                                 {
2992                                     // Check if curent chart type has more that 1 series and they are split 
2993                                     // by other series
2994                                     bool chartTypeIsSplit = false;
2995
2996                                     if (splitChartType.Contains(series.ChartTypeName))
2997                                     {
2998                                         chartTypeIsSplit = true;
2999                                     }
3000                                     else
3001                                     {
3002                                         bool otherChartTypeFound = false;
3003                                         for (int curentSeriesIndex = seriesIndex + 1; curentSeriesIndex < this.Common.DataManager.Series.Count; curentSeriesIndex++)
3004                                         {
3005                                             if (series.ChartTypeName == this.Common.DataManager.Series[curentSeriesIndex].ChartTypeName)
3006                                             {
3007                                                 if (otherChartTypeFound)
3008                                                 {
3009                                                     chartTypeIsSplit = true;
3010                                                     splitChartType.Add(series.ChartTypeName);
3011                                                 }
3012                                             }
3013                                             else
3014                                             {
3015                                                 if (this.Common.DataManager.Series[curentSeriesIndex].ChartType == SeriesChartType.Area ||
3016                                                     this.Common.DataManager.Series[curentSeriesIndex].ChartType == SeriesChartType.SplineArea)
3017                                                 {
3018                                                     otherChartTypeFound = true;
3019                                                 }
3020                                             }
3021                                         }
3022                                     }
3023
3024                                     if (chartTypeIsSplit)
3025                                     {
3026                                         // Add a record to process this series individually
3027                                         resultList.Add(new ChartTypeAndSeriesInfo(series));
3028                                     }
3029                                     else
3030                                     {
3031                                         // Add a record to process all series of that chart type at once
3032                                         resultList.Add(new ChartTypeAndSeriesInfo(series.ChartTypeName));
3033                                         processedChartType.Add(series.ChartTypeName);
3034                                     }
3035                                 }
3036                             }
3037                         }
3038
3039                         ++seriesIndex;
3040                     }
3041                 }
3042                 else
3043                 {
3044                     foreach (string chartType in this.ChartTypes)
3045                     {
3046                         resultList.Add(new ChartTypeAndSeriesInfo(chartType));
3047                     }
3048                 }
3049
3050                 return resultList;
3051             }
3052
3053             /// <summary>
3054             /// Internal data structure that stores chart type name and optionally series object.
3055             /// </summary>
3056             internal class ChartTypeAndSeriesInfo
3057             {
3058                 /// <summary>
3059                 /// Object constructor.
3060                 /// </summary>
3061                 public ChartTypeAndSeriesInfo()
3062                 {
3063                 }
3064
3065                 /// <summary>
3066                 /// Object constructor.
3067                 /// </summary>
3068                 /// <param name="chartType">Chart type name to initialize with.</param>
3069                 public ChartTypeAndSeriesInfo(string chartType)
3070                 {
3071                     this.ChartType = chartType;
3072                 }
3073
3074                 /// <summary>
3075                 /// Object constructor.
3076                 /// </summary>
3077                 /// <param name="series">Series to initialize with.</param>
3078                 public ChartTypeAndSeriesInfo(Series series)
3079                 {
3080                     this.ChartType = series.ChartTypeName;
3081                     this.Series = series;
3082                 }
3083
3084                 // Chart type name
3085                 internal string ChartType = string.Empty;
3086
3087                 // Series object. Can be set to NULL!
3088                 internal Series Series = null;
3089
3090             }
3091
3092             #endregion // 2D Series drawing order methods
3093
3094             #region IDisposable Members
3095
3096             /// <summary>
3097             /// Releases unmanaged and - optionally - managed resources
3098             /// </summary>
3099             /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
3100             [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "axisX")]
3101             [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "axisX2")]
3102             [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "axisY")]
3103             [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "axisY2")]
3104             protected override void Dispose(bool disposing)
3105             {
3106                 if (disposing)
3107                 {
3108                     // Dispose managed resources
3109                     if (this._axisArray != null)
3110                     {
3111                         foreach (Axis axis in this._axisArray)
3112                         {
3113                             axis.Dispose();
3114                         }
3115                         this._axisArray = null;
3116                     }
3117                     if ( this._areaPosition != null)
3118                     {
3119                         this._areaPosition.Dispose();
3120                         this._areaPosition = null;
3121                     }
3122                     if (this._innerPlotPosition != null)
3123                     {
3124                         this._innerPlotPosition.Dispose();
3125                         this._innerPlotPosition = null;
3126                     }
3127                     if (this.PlotAreaPosition != null)
3128                     {
3129                         this.PlotAreaPosition.Dispose();
3130                         this.PlotAreaPosition = null;
3131                     }
3132 #if Microsoft_CONTROL
3133                     if (this.areaBufferBitmap != null)
3134                     {
3135                         this.areaBufferBitmap.Dispose();
3136                         this.areaBufferBitmap = null;
3137                     }
3138                     if (this._cursorX != null)
3139                     {
3140                         this._cursorX.Dispose();
3141                         this._cursorX = null;
3142                     }
3143                     if (this._cursorY != null)
3144                     {
3145                         this._cursorY.Dispose();
3146                         this._cursorY = null;
3147                     }
3148 #endif
3149                 }
3150                 base.Dispose(disposing);
3151             }
3152
3153
3154             #endregion
3155
3156         }
3157 }