Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Web.DataVisualization / Common / General / ChartElement.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:               ChartElement.cs
9 //
10 //  Namespace:  System.Web.UI.WebControls[Windows.Forms].Charting
11 //
12 //      Classes:        ChartHelper
13 //
14 //  Purpose:    The chart element is base class for the big number 
15 //                              of classes. It stores common methods and data.
16 //
17 //      Reviewed:       GS - August 2, 2002
18 //                              AG - August 8, 2002
19 //              AG - Microsoft 16, 2007
20 //
21 //===================================================================
22
23
24 #region Used namespaces
25
26 using System;
27 using System.Drawing;
28 using System.Drawing.Drawing2D;
29 using System.Collections;
30 using System.Diagnostics.CodeAnalysis;
31 using System.Collections.Generic;
32 using System.Collections.ObjectModel;
33
34 #endregion
35
36 #if Microsoft_CONTROL
37         namespace System.Windows.Forms.DataVisualization.Charting
38 #else
39 namespace System.Web.UI.DataVisualization.Charting
40
41 #endif
42 {
43         #region Enumerations
44
45                 /// <summary>
46                 /// An enumeration that specifies a label alignment.
47                 /// </summary>
48                 [
49                 Flags
50                 ]
51                 public enum LabelAlignmentStyles
52                 {
53                         /// <summary>
54                         /// Label is aligned to the top of the data point.
55                         /// </summary>
56                         Top = 1,
57                         /// <summary>
58                         /// Label is aligned to the bottom of the data point.
59                         /// </summary>
60                         Bottom = 2,
61                         /// <summary>
62                         /// Label is aligned to the right of the data point.
63                         /// </summary>
64                         Right = 4,
65                         /// <summary>
66                         /// Label is aligned to the left of the data point.
67                         /// </summary>
68                         Left = 8,
69                         /// <summary>
70                         /// Label is aligned to the top-left corner of the data point.
71                         /// </summary>
72                         TopLeft = 16,
73                         /// <summary>
74                         /// Label is aligned to the top-right corner of the data point.
75                         /// </summary>
76                         TopRight = 32,
77                         /// <summary>
78                         /// Label is aligned to the bottom-left of the data point.
79                         /// </summary>
80                         BottomLeft = 64,
81                         /// <summary>
82                         /// Label is aligned to the bottom-right of the data point.
83                         /// </summary>
84                         BottomRight = 128,
85                         /// <summary>
86                         /// Label is aligned to the center of the data point.
87                         /// </summary>
88                         Center = 256,
89                 }
90
91         /// <summary>
92         /// An enumeration of chart types.
93         /// </summary>
94         public enum SeriesChartType
95         {       
96                 /// <summary>
97                 /// Point chart type.
98                 /// </summary>
99                 Point,
100
101                 /// <summary>
102                 /// FastPoint chart type.
103                 /// </summary>
104                 FastPoint,
105
106                 /// <summary>
107                 /// Bubble chart type.
108                 /// </summary>
109                 Bubble,
110                 /// <summary>
111                 /// Line chart type.
112                 /// </summary>
113                 Line,
114                 /// <summary>
115                 /// Spline chart type.
116                 /// </summary>
117                 Spline,
118                 /// <summary>
119                 /// StepLine chart type.
120                 /// </summary>
121                 StepLine,
122
123                 /// <summary>
124                 /// FastLine chart type.
125                 /// </summary>
126                 FastLine,
127
128                 /// <summary>
129                 /// Bar chart type.
130                 /// </summary>
131                 Bar,
132                 /// <summary>
133                 /// Stacked bar chart type.
134                 /// </summary>
135                 StackedBar,
136                 /// <summary>
137                 /// Hundred percent stacked bar chart type.
138                 /// </summary>
139                 StackedBar100,
140                 /// <summary>
141                 /// Column chart type.
142                 /// </summary>
143                 Column,
144                 /// <summary>
145                 /// Stacked column chart type.
146                 /// </summary>
147                 StackedColumn,
148                 /// <summary>
149                 /// Hundred percent stacked column chart type.
150                 /// </summary>
151                 StackedColumn100,
152                 /// <summary>
153                 /// Area chart type.
154                 /// </summary>
155                 Area,
156                 /// <summary>
157                 /// Spline area chart type.
158                 /// </summary>
159                 SplineArea,
160                 /// <summary>
161                 /// Stacked area chart type.
162                 /// </summary>
163                 StackedArea,
164                 /// <summary>
165                 /// Hundred percent stacked area chart type.
166                 /// </summary>
167                 StackedArea100,
168                 /// <summary>
169                 /// Pie chart type.
170                 /// </summary>
171                 Pie,
172                 /// <summary>
173                 /// Doughnut chart type.
174                 /// </summary>
175                 Doughnut,
176                 /// <summary>
177                 /// Stock chart type.
178                 /// </summary>
179                 Stock,
180                 /// <summary>
181                 /// CandleStick chart type.
182                 /// </summary>
183                 Candlestick,
184                 /// <summary>
185                 /// Range chart type.
186                 /// </summary>
187                 Range,
188                 /// <summary>
189                 /// Spline range chart type.
190                 /// </summary>
191                 SplineRange,
192                 /// <summary>
193                 /// RangeBar chart type.
194                 /// </summary>
195                 RangeBar,
196                 /// <summary>
197                 /// Range column chart type.
198                 /// </summary>
199                 RangeColumn,
200                 /// <summary>
201                 /// Radar chart type.
202                 /// </summary>
203                 Radar,
204                 /// <summary>
205                 /// Polar chart type.
206                 /// </summary>
207                 Polar,
208                 /// <summary>
209                 /// Error bar chart type.
210                 /// </summary>
211                 ErrorBar,
212                 /// <summary>
213                 /// Box plot chart type.
214                 /// </summary>
215                 BoxPlot,
216                 /// <summary>
217                 /// Renko chart type.
218                 /// </summary>
219         [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Renko")]
220         Renko,
221                 /// <summary>
222                 /// ThreeLineBreak chart type.
223                 /// </summary>
224                 ThreeLineBreak,
225                 /// <summary>
226                 /// Kagi chart type.
227                 /// </summary>
228         [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Kagi")]
229         Kagi,
230                 /// <summary>
231                 /// PointAndFigure chart type.
232                 /// </summary>
233                 PointAndFigure,
234                 /// <summary>
235                 /// Funnel chart type.
236                 /// </summary>
237                 Funnel,
238                 /// <summary>
239                 /// Pyramid chart type.
240                 /// </summary>
241                 Pyramid,
242         }
243
244         /// <summary>
245         /// Axis Arrow orientation
246         /// </summary>
247         internal enum ArrowOrientation
248         {
249                 /// <summary>
250                 /// Arrow direction is Right - Left
251                 /// </summary>
252                 Left, 
253                 /// <summary>
254                 /// Arrow direction is Left - Right
255                 /// </summary>
256                 Right, 
257                 /// <summary>
258                 /// Arrow direction is Bottom - Top
259                 /// </summary>
260                 Top,
261                 /// <summary>
262                 /// Arrow direction is Top - Bottom
263                 /// </summary>
264                 Bottom
265         }
266
267         /// <summary>
268         /// An enumeration of image alignment.
269         /// </summary>
270         public enum ChartImageAlignmentStyle
271         {
272                 /// <summary>
273         /// The mage is aligned to the top left corner of the chart element.
274                 /// </summary>
275                 TopLeft,
276                 /// <summary>
277         /// The image is aligned to the top boundary of the chart element.
278                 /// </summary>
279                 Top,
280                 /// <summary>
281         /// The image is aligned to the top right corner of the chart element.
282                 /// </summary>
283                 TopRight,
284                 /// <summary>
285         /// The image is aligned to the right boundary of the chart element.
286                 /// </summary>
287                 Right,
288                 /// <summary>
289         /// The image is aligned to the bottom right corner of the chart element.
290                 /// </summary>
291                 BottomRight,
292                 /// <summary>
293         /// The image is aligned to the bottom boundary of the chart element.
294                 /// </summary>
295                 Bottom,
296                 /// <summary>
297         /// The image is aligned to the bottom left corner of the chart element.
298                 /// </summary>
299                 BottomLeft,
300                 /// <summary>
301         /// The image is aligned to the left boundary of the chart element.
302                 /// </summary>
303                 Left,
304                 /// <summary>
305         /// The image is aligned in the center of the chart element.
306                 /// </summary>
307                 Center
308         };
309
310         /// <summary>
311     /// An enumeration that specifies a background image drawing mode.
312         /// </summary>
313         public enum ChartImageWrapMode
314         {
315                 /// <summary>
316         /// Background image is scaled to fit the entire chart element.
317                 /// </summary>          
318                 Scaled = WrapMode.Clamp,
319
320                 /// <summary>
321         /// Background image is tiled to fit the entire chart element.
322                 /// </summary>
323                 Tile = WrapMode.Tile,
324
325                 /// <summary>
326         /// Every other tiled image is reversed around the X-axis.
327                 /// </summary>
328                 TileFlipX = WrapMode.TileFlipX,
329
330                 /// <summary>
331         /// Every other tiled image is reversed around the X-axis and Y-axis.
332                 /// </summary>
333                 TileFlipXY = WrapMode.TileFlipXY,
334
335                 /// <summary>
336         /// Every other tiled image is reversed around the Y-axis.
337                 /// </summary>
338                 TileFlipY = WrapMode.TileFlipY,
339
340                 /// <summary>
341         /// Background image is not scaled.
342                 /// </summary>
343         [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Unscaled")]
344         Unscaled = 100
345         };
346
347         /// <summary>
348     /// An enumeration that specifies the state of an axis.
349         /// </summary>
350         public enum AxisEnabled
351         {
352                 /// <summary>
353         /// The axis is only enabled if it used to plot a Series.
354                 /// </summary>
355                 Auto,
356                 
357                 /// <summary>
358                 /// The axis is always enabled.
359                 /// </summary>
360                 True,
361                 
362                 /// <summary>
363                 /// The axis is never enabled.
364                 /// </summary>
365                 False
366
367         };
368
369         /// <summary>
370         /// An enumeration of units of measurement of an interval.
371         /// </summary>
372         public enum DateTimeIntervalType
373         {
374                 /// <summary>
375         /// Automatically determined by the Chart control.
376                 /// </summary>
377                 Auto, 
378                 
379                 /// <summary>
380                 /// The interval is numerical.
381                 /// </summary>
382                 Number, 
383                 
384                 /// <summary>
385                 /// The interval is years.
386                 /// </summary>
387                 Years, 
388                 
389                 /// <summary>
390                 /// The interval is months.
391                 /// </summary>
392                 Months, 
393                 
394                 /// <summary>
395         /// The interval is weeks.
396                 /// </summary>
397                 Weeks, 
398                 
399                 /// <summary>
400                 /// The interval is days.
401                 /// </summary>
402                 Days, 
403                 
404                 /// <summary>
405                 /// The interval is hours.
406                 /// </summary>
407                 Hours, 
408                 
409                 /// <summary>
410                 /// The interval is minutes.
411                 /// </summary>
412                 Minutes,
413
414                 /// <summary>
415                 /// The interval is seconds.
416                 /// </summary>
417                 Seconds,
418                 
419                 /// <summary>
420                 /// The interval is milliseconds.
421                 /// </summary>
422                 Milliseconds,
423
424                 /// <summary>
425                 /// The interval type is not defined.
426                 /// </summary>
427                 NotSet, 
428         }
429
430         /// <summary>
431     /// An enumeration that specifies value types for various chart properties
432         /// </summary>
433         public enum ChartValueType
434         { 
435                 /// <summary>
436         /// Property type is set automatically by the Chart control.
437                 /// </summary>
438                 Auto, 
439                 
440                 /// <summary>
441                 /// Double value.
442                 /// </summary>
443                 Double, 
444                 
445                 /// <summary>
446                 /// Single value.
447                 /// </summary>
448                 Single, 
449                 
450                 /// <summary>
451                 /// Int32 value.
452                 /// </summary>
453                 Int32, 
454                 
455                 /// <summary>
456                 /// Int64 value.
457                 /// </summary>
458                 Int64, 
459                 
460                 /// <summary>
461                 /// UInt32 value.
462                 /// </summary>
463         [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly",
464             Justification = "These names are patterned after the standard CLR types for consistency")]
465                 UInt32, 
466                 
467                 /// <summary>
468                 /// UInt64 value.
469                 /// </summary>
470         [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly",
471             Justification = "These names are patterned after the standard CLR types for consistency")]
472                 UInt64, 
473                 
474                 /// <summary>
475                 /// String value.
476                 /// </summary>
477                 String, 
478                 
479                 /// <summary>
480                 /// DateTime value.
481                 /// </summary>
482                 DateTime,
483
484                 /// <summary>
485                 /// Date portion of the DateTime value.
486                 /// </summary>
487                 Date,
488
489                 /// <summary>
490                 /// Time portion of the DateTime value.
491                 /// </summary>
492                 Time,
493
494         /// <summary>
495                 /// DateTime with offset
496                 /// </summary>
497                 DateTimeOffset
498         };
499
500         /// <summary>
501         /// An enumeration that specifies a hatching style.
502         /// </summary>
503         public enum ChartHatchStyle 
504         { 
505                 /// <summary>
506                 /// No hatching style.
507                 /// </summary>
508                 None, 
509                 /// <summary>
510                 /// Backward diagonal style.
511                 /// </summary>
512                 BackwardDiagonal, 
513                 /// <summary>
514                 /// Cross style.
515                 /// </summary>
516                 Cross, 
517                 /// <summary>
518                 /// Dark downward diagonal style.
519                 /// </summary>
520                 DarkDownwardDiagonal, 
521                 /// <summary>
522                 /// Dark horizontal style.
523                 /// </summary>
524                 DarkHorizontal, 
525                 /// <summary>
526                 /// Dark upward diagonal style.
527                 /// </summary>
528                 DarkUpwardDiagonal, 
529                 /// <summary>
530                 /// Dark vertical style.
531                 /// </summary>
532                 DarkVertical, 
533                 /// <summary>
534                 /// Dashed downward diagonal style.
535                 /// </summary>
536                 DashedDownwardDiagonal,
537                 /// <summary>
538                 /// Dashed horizontal style.
539                 /// </summary>
540                 DashedHorizontal, 
541                 /// <summary>
542                 /// Dashed upward diagonal style.
543                 /// </summary>
544                 DashedUpwardDiagonal, 
545                 /// <summary>
546                 /// Dashed vertical style.
547                 /// </summary>
548                 DashedVertical, 
549                 /// <summary>
550                 /// Diagonal brick style.
551                 /// </summary>
552                 DiagonalBrick, 
553                 /// <summary>
554                 /// Diagonal cross style.
555                 /// </summary>
556                 DiagonalCross, 
557                 /// <summary>
558                 /// Divot style.
559                 /// </summary>
560                 Divot, 
561                 /// <summary>
562                 /// Dotted diamond style.
563                 /// </summary>
564                 DottedDiamond, 
565                 /// <summary>
566                 /// Dotted grid style.
567                 /// </summary>
568                 DottedGrid, 
569                 /// <summary>
570                 /// Forward diagonal style.
571                 /// </summary>
572                 ForwardDiagonal, 
573                 /// <summary>
574                 /// Horizontal style.
575                 /// </summary>
576                 Horizontal, 
577                 /// <summary>
578                 /// Horizontal brick style.
579                 /// </summary>
580                 HorizontalBrick, 
581                 /// <summary>
582                 /// Large checker board style.
583                 /// </summary>
584         [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "CheckerBoard")]
585         LargeCheckerBoard, 
586                 /// <summary>
587                 /// Large confetti style.
588                 /// </summary>
589                 LargeConfetti, 
590                 /// <summary>
591                 /// Large grid style.
592                 /// </summary>
593                 LargeGrid, 
594                 /// <summary>
595                 /// Light downward diagonal style.
596                 /// </summary>
597                 LightDownwardDiagonal, 
598                 /// <summary>
599                 /// Light horizontal style.
600                 /// </summary>
601                 LightHorizontal, 
602                 /// <summary>
603                 /// Light upward diagonal style.
604                 /// </summary>
605                 LightUpwardDiagonal, 
606                 /// <summary>
607                 /// Light vertical style.
608                 /// </summary>
609                 LightVertical, 
610                 /// <summary>
611                 /// Narrow horizontal style.
612                 /// </summary>
613                 NarrowHorizontal, 
614                 /// <summary>
615                 /// Narrow vertical style.
616                 /// </summary>
617                 NarrowVertical, 
618                 /// <summary>
619                 /// Outlined diamond style.
620                 /// </summary>
621                 OutlinedDiamond, 
622                 /// <summary>
623                 /// Percent05 style.
624                 /// </summary>
625                 Percent05, 
626                 /// <summary>
627                 /// Percent10 style.
628                 /// </summary>
629                 Percent10, 
630                 /// <summary>
631                 /// Percent20 style.
632                 /// </summary>
633                 Percent20, 
634                 /// <summary>
635                 /// Percent25 style.
636                 /// </summary>
637                 Percent25, 
638                 /// <summary>
639                 /// Percent30 style.
640                 /// </summary>
641                 Percent30, 
642                 /// <summary>
643                 /// Percent40 style.
644                 /// </summary>
645                 Percent40, 
646                 /// <summary>
647                 /// Percent50 style.
648                 /// </summary>
649                 Percent50, 
650                 /// <summary>
651                 /// Percent60 style.
652                 /// </summary>
653                 Percent60, 
654                 /// <summary>
655                 /// Percent70 style.
656                 /// </summary>
657                 Percent70, 
658                 /// <summary>
659                 /// Percent75 style.
660                 /// </summary>
661                 Percent75, 
662                 /// <summary>
663                 /// Percent80 style.
664                 /// </summary>
665                 Percent80, 
666                 /// <summary>
667                 /// Percent90 style.
668                 /// </summary>
669                 Percent90, 
670                 /// <summary>
671                 /// Plaid style.
672                 /// </summary>
673                 Plaid, 
674                 /// <summary>
675                 /// Shingle style.
676                 /// </summary>
677                 Shingle, 
678                 /// <summary>
679                 /// Small checker board style.
680                 /// </summary>
681         [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "CheckerBoard")]
682         SmallCheckerBoard,
683                 /// <summary>
684                 /// Small confetti style.
685                 /// </summary>
686                 SmallConfetti, 
687                 /// <summary>
688                 /// Small grid style.
689                 /// </summary>
690                 SmallGrid, 
691                 /// <summary>
692                 /// Solid diamond style.
693                 /// </summary>
694                 SolidDiamond, 
695                 /// <summary>
696                 /// Sphere style.
697                 /// </summary>
698                 Sphere, 
699                 /// <summary>
700                 /// Trellis style.
701                 /// </summary>
702                 Trellis, 
703                 /// <summary>
704                 /// Vertical style.
705                 /// </summary>
706                 Vertical, 
707                 /// <summary>
708                 /// Wave style.
709                 /// </summary>
710                 Wave, 
711                 /// <summary>
712                 /// Weave style.
713                 /// </summary>
714                 Weave, 
715                 /// <summary>
716                 /// Wide downward diagonal style.
717                 /// </summary>
718                 WideDownwardDiagonal, 
719                 /// <summary>
720                 /// Wide upward diagonal style.
721                 /// </summary>
722                 WideUpwardDiagonal, 
723                 /// <summary>
724                 /// ZigZag style.
725                 /// </summary>
726         [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "ZigZag")]
727         [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Zig")]
728         [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Zag")]
729         ZigZag
730         };
731
732         /// <summary>
733     /// An enumeration that specifies the level of anti-aliasing quality.
734         /// </summary>
735         public enum TextAntiAliasingQuality
736         {
737                 /// <summary>
738                 /// Normal anti-aliasing quality.
739                 /// </summary>
740                 Normal,
741                 /// <summary>
742                 /// High anti-aliasing quality.
743                 /// </summary>
744                 High,
745                 /// <summary>
746                 /// System default anti-aliasing quality.
747                 /// </summary>
748                 SystemDefault
749         }
750
751         /// <summary>
752         /// An enumeration of anti-aliasing flags.
753         /// </summary>
754         [Flags]
755         public enum AntiAliasingStyles
756         {
757                 /// <summary>
758                 /// No anti-aliasing.
759                 /// </summary>
760                 None = 0,
761
762                 /// <summary>
763                 /// Use anti-aliasing when drawing text.
764                 /// </summary>
765                 Text = 1,
766
767                 /// <summary>
768                 /// Use anti-aliasing when drawing grahics primitives (e.g. lines, rectangle)
769                 /// </summary>
770                 Graphics = 2,
771
772                 /// <summary>
773                 /// Use anti-alias for everything.
774                 /// </summary>
775                 All = Text | Graphics
776
777         };
778         
779         /// <summary>
780         /// An enumeration of marker styles.
781         /// </summary>
782         public enum MarkerStyle
783         {
784                 /// <summary>
785         /// No marker is displayed for the series/data point.
786                 /// </summary>
787                 None = 0, 
788
789                 /// <summary>
790         /// A square marker is displayed.
791                 /// </summary>
792                 Square = 1, 
793
794                 /// <summary>
795         /// A circle marker is displayed.
796                 /// </summary>
797                 Circle = 2, 
798
799                 /// <summary>
800         /// A diamond-shaped marker is displayed.
801                 /// </summary>
802                 Diamond = 3, 
803
804                 /// <summary>
805         /// A triangular marker is displayed.
806                 /// </summary>
807                 Triangle = 4, 
808
809                 /// <summary>
810         /// A cross-shaped marker is displayed.
811                 /// </summary>
812                 Cross = 5,
813
814                 /// <summary>
815         /// A 4-point star-shaped marker is displayed.
816                 /// </summary>
817                 Star4 = 6,
818
819                 /// <summary>
820         /// A 5-point star-shaped marker is displayed.
821                 /// </summary>
822                 Star5 = 7,
823
824                 /// <summary>
825         /// A 6-point star-shaped marker is displayed.
826                 /// </summary>
827                 Star6 = 8,
828
829                 /// <summary>
830         /// A 10-point star-shaped marker is displayed.
831                 /// </summary>
832                 Star10 = 9
833
834         };
835
836         /// <summary>
837         /// An enumeration of gradient styles.
838         /// </summary>
839         public enum GradientStyle
840         {
841                 /// <summary>
842         /// No gradient is used.
843                 /// </summary>
844                 None, 
845                 
846                 /// <summary>
847         /// Gradient is applied from left to right.
848                 /// </summary>
849                 LeftRight, 
850                 
851                 /// <summary>
852         /// Gradient is applied from top to bottom.
853                 /// </summary>
854                 TopBottom, 
855                 
856                 /// <summary>
857         /// Gradient is applied from the center outwards.
858                 /// </summary>
859                 Center, 
860                 
861                 /// <summary>
862         /// Gradient is applied diagonally from left to right.
863                 /// </summary>
864                 DiagonalLeft, 
865                 
866                 /// <summary>
867         /// Gradient is applied diagonally from right to left.
868                 /// </summary>
869                 DiagonalRight, 
870                 
871                 /// <summary>
872         /// Gradient is applied horizontally from the center outwards.
873                 /// </summary>
874                 HorizontalCenter, 
875                 
876                 /// <summary>
877         /// Gradient is applied vertically from the center outwards.
878                 /// </summary>
879                 VerticalCenter
880         };
881
882         #endregion
883     
884     #region ChartElement
885
886     /// <summary>
887     /// Common chart helper methods used across different chart elements.
888     /// </summary>
889     internal class ChartHelper
890     {
891         #region Fields
892
893         /// <summary>
894         /// Maximum number of grid lines per Axis
895         /// </summary>
896         internal const int MaxNumOfGridlines = 10000;
897
898         #endregion // Fields
899
900         #region Constructor
901
902         /// <summary>
903         /// Private constructor to avoid instantiating the class
904         /// </summary>
905         private ChartHelper() { }
906
907         #endregion // Constructor
908
909         #region Methods
910
911         /// <summary>
912                 /// Adjust the beginnin of the first interval depending on the type and size.
913                 /// </summary>
914                 /// <param name="start">Original start point.</param>
915                 /// <param name="intervalSize">Interval size.</param>
916                 /// <param name="type">AxisName of the interval (Month, Year, ...).</param>
917                 /// <returns>Adjusted interval start position as double.</returns>
918         internal static double AlignIntervalStart(double start, double intervalSize, DateTimeIntervalType type)
919                 {
920                         return AlignIntervalStart(start, intervalSize, type, null);
921                 }
922
923                 /// <summary>
924                 /// Adjust the beginnin of the first interval depending on the type and size.
925                 /// </summary>
926                 /// <param name="start">Original start point.</param>
927                 /// <param name="intervalSize">Interval size.</param>
928                 /// <param name="type">AxisName of the interval (Month, Year, ...).</param>
929                 /// <param name="series">First series connected to the axis.</param>
930                 /// <returns>Adjusted interval start position as double.</returns>
931         internal static double AlignIntervalStart(double start, double intervalSize, DateTimeIntervalType type, Series series)
932                 {
933                         return AlignIntervalStart( start, intervalSize, type, series, true );
934                 }
935
936                 /// <summary>
937                 /// Adjust the beginnin of the first interval depending on the type and size.
938                 /// </summary>
939                 /// <param name="start">Original start point.</param>
940                 /// <param name="intervalSize">Interval size.</param>
941                 /// <param name="type">AxisName of the interval (Month, Year, ...).</param>
942                 /// <param name="series">First series connected to the axis.</param>
943                 /// <param name="majorInterval">Interval is used for major gridlines or tickmarks.</param>
944                 /// <returns>Adjusted interval start position as double.</returns>
945         internal static double AlignIntervalStart(double start, double intervalSize, DateTimeIntervalType type, Series series, bool majorInterval)
946                 {
947                         // Special case for indexed series
948                         if(series != null && series.IsXValueIndexed)
949                         {
950                                 if(type == DateTimeIntervalType.Auto ||
951                                         type == DateTimeIntervalType.Number)
952                                 {
953                                         if( majorInterval )
954                                         {
955                                                 return 1;
956                                         }
957                                         else
958                                         {
959                                                 return 0;
960                                         }
961                                 }
962                                         
963                                 return -(series.Points.Count + 1);
964                         }
965
966                         // Non indexed series
967                         else
968                         {
969                                 // Do not adjust start position for these interval type
970                                 if(type == DateTimeIntervalType.Auto ||
971                                         type == DateTimeIntervalType.Number)
972                                 {
973                                         return start;
974                                 }
975
976                                 // Get the beginning of the interval depending on type
977                                 DateTime        newStartDate = DateTime.FromOADate(start);
978
979                                 // Adjust the months interval depending on size
980                                 if(intervalSize > 0.0 && intervalSize != 1.0)
981                                 {
982                                         if(type == DateTimeIntervalType.Months && intervalSize <= 12.0 && intervalSize > 1)
983                                         {
984                                                 // Make sure that the beginning is aligned correctly for cases
985                                                 // like quarters and half years
986                                                 DateTime        resultDate = newStartDate;
987                                                 DateTime        sizeAdjustedDate = new DateTime(newStartDate.Year, 1, 1, 0, 0, 0);
988                                                 while(sizeAdjustedDate < newStartDate)
989                                                 {
990                                                         resultDate = sizeAdjustedDate;
991                                                         sizeAdjustedDate = sizeAdjustedDate.AddMonths((int)intervalSize);
992                                                 }
993
994                                                 newStartDate = resultDate;
995                                                 return newStartDate.ToOADate();
996                                         }
997                                 }
998
999                                 // Check interval type
1000                                 switch(type)
1001                                 {
1002                                         case(DateTimeIntervalType.Years):
1003                                                 int year = (int)((int)(newStartDate.Year / intervalSize) * intervalSize);
1004                                                 if(year <= 0)
1005                                                 {
1006                                                         year = 1;
1007                                                 }
1008                                                 newStartDate = new DateTime(year, 
1009                                                         1, 1, 0, 0, 0);
1010                                                 break;
1011
1012                                         case(DateTimeIntervalType.Months):
1013                                                 int month = (int)((int)(newStartDate.Month / intervalSize) * intervalSize);
1014                                                 if(month <= 0)
1015                                                 {
1016                                                         month = 1;
1017                                                 }
1018                                                 newStartDate = new DateTime(newStartDate.Year, 
1019                                                         month, 1, 0, 0, 0);
1020                                                 break;
1021
1022                                         case(DateTimeIntervalType.Days):
1023                                                 int day = (int)((int)(newStartDate.Day / intervalSize) * intervalSize);
1024                                                 if(day <= 0)
1025                                                 {
1026                                                         day = 1;
1027                                                 }
1028                                                 newStartDate = new DateTime(newStartDate.Year, 
1029                                                         newStartDate.Month, day, 0, 0, 0);
1030                                                 break;
1031
1032                                         case(DateTimeIntervalType.Hours):
1033                                                 int hour = (int)((int)(newStartDate.Hour / intervalSize) * intervalSize);
1034                                                 newStartDate = new DateTime(newStartDate.Year, 
1035                                                         newStartDate.Month, newStartDate.Day, hour, 0, 0);
1036                                                 break;
1037
1038                                         case(DateTimeIntervalType.Minutes):
1039                                                 int minute = (int)((int)(newStartDate.Minute / intervalSize) * intervalSize);
1040                                                 newStartDate = new DateTime(newStartDate.Year, 
1041                                                         newStartDate.Month, 
1042                                                         newStartDate.Day, 
1043                                                         newStartDate.Hour, 
1044                                                         minute, 
1045                                                         0);
1046                                                 break;
1047
1048                                         case(DateTimeIntervalType.Seconds):
1049                                                 int second = (int)((int)(newStartDate.Second / intervalSize) * intervalSize);
1050                                                 newStartDate = new DateTime(newStartDate.Year, 
1051                                                         newStartDate.Month, 
1052                                                         newStartDate.Day, 
1053                                                         newStartDate.Hour, 
1054                                                         newStartDate.Minute, 
1055                                                         second, 
1056                                                         0);
1057                                                 break;
1058
1059                                         case(DateTimeIntervalType.Milliseconds):
1060                                                 int milliseconds = (int)((int)(newStartDate.Millisecond / intervalSize) * intervalSize);
1061                                                 newStartDate = new DateTime(newStartDate.Year, 
1062                                                         newStartDate.Month, 
1063                                                         newStartDate.Day, 
1064                                                         newStartDate.Hour, 
1065                                                         newStartDate.Minute, 
1066                                                         newStartDate.Second, 
1067                                                         milliseconds);
1068                                                 break;
1069
1070                                         case(DateTimeIntervalType.Weeks):
1071
1072                         // NOTE: Code below was changed to fix issue #5962
1073                         // Elements that have interval set to weeks should be aligned to the 
1074                         // nearest Monday no matter how many weeks is the interval.
1075                                                 //newStartDate = newStartDate.AddDays(-((int)newStartDate.DayOfWeek * intervalSize));
1076                         newStartDate = newStartDate.AddDays(-((int)newStartDate.DayOfWeek));
1077                                                 newStartDate = new DateTime(newStartDate.Year, 
1078                                                         newStartDate.Month, newStartDate.Day, 0, 0, 0);
1079                                                 break;
1080                                 }
1081
1082                                 return newStartDate.ToOADate();
1083                         }
1084                 }
1085
1086
1087                 /// <summary>
1088                 /// Gets interval size as double number.
1089                 /// </summary>
1090                 /// <param name="current">Current value.</param>
1091                 /// <param name="interval">Interval size.</param>
1092                 /// <param name="type">AxisName of the interval (Month, Year, ...).</param>
1093                 /// <returns>Interval size as double.</returns>
1094         internal static double GetIntervalSize(double current, double interval, DateTimeIntervalType type)
1095                 {
1096                         return GetIntervalSize(
1097                                 current, 
1098                                 interval, 
1099                                 type, 
1100                                 null, 
1101                                 0, 
1102                                 DateTimeIntervalType.Number, 
1103                                 true, 
1104                                 true);
1105                 }
1106
1107                 /// <summary>
1108                 /// Gets interval size as double number.
1109                 /// </summary>
1110                 /// <param name="current">Current value.</param>
1111                 /// <param name="interval">Interval size.</param>
1112                 /// <param name="type">AxisName of the interval (Month, Year, ...).</param>
1113                 /// <param name="series">First series connected to the axis.</param>
1114                 /// <param name="intervalOffset">Offset size.</param>
1115                 /// <param name="intervalOffsetType">Offset type(Month, Year, ...).</param>
1116                 /// <param name="forceIntIndex">Force Integer indexed</param>
1117                 /// <returns>Interval size as double.</returns>
1118         internal static double GetIntervalSize(
1119                         double current, 
1120                         double interval, 
1121                         DateTimeIntervalType type, 
1122                         Series series,
1123                         double intervalOffset, 
1124                         DateTimeIntervalType intervalOffsetType,
1125                         bool forceIntIndex)
1126                 {
1127                         return GetIntervalSize(
1128                                 current, 
1129                                 interval, 
1130                                 type, 
1131                                 series,
1132                                 intervalOffset, 
1133                                 intervalOffsetType,
1134                                 forceIntIndex,
1135                                 true);
1136                 }
1137
1138                 /// <summary>
1139                 /// Gets interval size as double number.
1140                 /// </summary>
1141                 /// <param name="current">Current value.</param>
1142                 /// <param name="interval">Interval size.</param>
1143                 /// <param name="type">AxisName of the interval (Month, Year, ...).</param>
1144                 /// <param name="series">First series connected to the axis.</param>
1145                 /// <param name="intervalOffset">Offset size.</param>
1146                 /// <param name="intervalOffsetType">Offset type(Month, Year, ...).</param>
1147                 /// <param name="forceIntIndex">Force Integer indexed</param>
1148                 /// <param name="forceAbsInterval">Force Integer indexed</param>
1149                 /// <returns>Interval size as double.</returns>
1150         internal static double GetIntervalSize(
1151                         double current, 
1152                         double interval, 
1153                         DateTimeIntervalType type, 
1154                         Series series,
1155                         double intervalOffset, 
1156                         DateTimeIntervalType intervalOffsetType,
1157                         bool forceIntIndex,
1158                         bool forceAbsInterval)
1159                 {
1160                         // AxisName is not date.
1161                         if( type == DateTimeIntervalType.Number || type == DateTimeIntervalType.Auto )
1162                         {
1163                                 return interval;
1164                         }
1165
1166                         // Special case for indexed series
1167                         if(series != null && series.IsXValueIndexed)
1168                         {
1169                                 // Check point index
1170                                 int pointIndex = (int)Math.Ceiling(current - 1);
1171                                 if(pointIndex < 0)
1172                                 {
1173                                         pointIndex = 0;
1174                                 }
1175                                 if(pointIndex >= series.Points.Count || series.Points.Count <= 1)
1176                                 {
1177                                         return interval;
1178                                 }
1179
1180                                 // Get starting and ending values of the closest interval
1181                                 double          adjuster = 0;
1182                                 double          xValue = series.Points[pointIndex].XValue;
1183                                 xValue = AlignIntervalStart(xValue, 1, type, null);
1184                                 double          xEndValue = xValue + GetIntervalSize(xValue, interval, type);
1185                                 xEndValue += GetIntervalSize(xEndValue, intervalOffset, intervalOffsetType);
1186                                 xValue += GetIntervalSize(xValue, intervalOffset, intervalOffsetType);
1187                                 if(intervalOffset < 0)
1188                                 {
1189                                         xValue = xValue + GetIntervalSize(xValue, interval, type);
1190                                         xEndValue = xEndValue + GetIntervalSize(xEndValue, interval, type);
1191                                 }
1192
1193                                 // The first point in the series
1194                                 if(pointIndex == 0 && current < 0)
1195                                 {
1196                                         // Round the first point value depending on the interval type
1197                                         DateTime        dateValue = DateTime.FromOADate(series.Points[pointIndex].XValue);
1198                                         DateTime        roundedDateValue = dateValue;
1199                                         switch(type)
1200                                         {
1201                                                 case(DateTimeIntervalType.Years): // Ignore hours,...
1202                                                         roundedDateValue = new DateTime(dateValue.Year, 
1203                                                                 dateValue.Month, dateValue.Day, 0, 0, 0);
1204                                                         break;
1205
1206                                                 case(DateTimeIntervalType.Months): // Ignore hours,...
1207                                                         roundedDateValue = new DateTime(dateValue.Year, 
1208                                                                 dateValue.Month, dateValue.Day, 0, 0, 0);
1209                                                         break;
1210
1211                                                 case(DateTimeIntervalType.Days): // Ignore hours,...
1212                                                         roundedDateValue = new DateTime(dateValue.Year, 
1213                                                                 dateValue.Month, dateValue.Day, 0, 0, 0);
1214                                                         break;
1215
1216                                                 case(DateTimeIntervalType.Hours): //
1217                                                         roundedDateValue = new DateTime(dateValue.Year, 
1218                                                                 dateValue.Month, dateValue.Day, dateValue.Hour, 
1219                                                                 dateValue.Minute, 0);
1220                                                         break;
1221
1222                                                 case(DateTimeIntervalType.Minutes):
1223                                                         roundedDateValue = new DateTime(dateValue.Year, 
1224                                                                 dateValue.Month, 
1225                                                                 dateValue.Day, 
1226                                                                 dateValue.Hour, 
1227                                                                 dateValue.Minute, 
1228                                                                 dateValue.Second);
1229                                                         break;
1230
1231                                                 case(DateTimeIntervalType.Seconds):
1232                                                         roundedDateValue = new DateTime(dateValue.Year, 
1233                                                                 dateValue.Month, 
1234                                                                 dateValue.Day, 
1235                                                                 dateValue.Hour, 
1236                                                                 dateValue.Minute, 
1237                                                                 dateValue.Second,
1238                                                                 0);
1239                                                         break;
1240
1241                                                 case(DateTimeIntervalType.Weeks):
1242                                                         roundedDateValue = new DateTime(dateValue.Year, 
1243                                                                 dateValue.Month, dateValue.Day, 0, 0, 0);
1244                                                         break;
1245                                         }
1246
1247                                         // The first point value is exactly on the interval boundaries
1248                                         if(roundedDateValue.ToOADate() == xValue || roundedDateValue.ToOADate() == xEndValue)
1249                                         {
1250                                                 return - current + 1;
1251                                         }
1252                                 }
1253
1254                                 // Adjuster of 0.5 means that position should be between points
1255                                 ++pointIndex;
1256                                 while(pointIndex < series.Points.Count)
1257                                 {
1258                                         if(series.Points[pointIndex].XValue >= xEndValue)
1259                                         {
1260                                                 if(series.Points[pointIndex].XValue > xEndValue && !forceIntIndex)
1261                                                 {
1262                                                         adjuster = -0.5;
1263                                                 }
1264                                                 break;
1265                                         }
1266
1267                                         ++pointIndex;
1268                                 }
1269
1270                                 // If last point outside of the max series index
1271                                 if(pointIndex == series.Points.Count)
1272                                 {
1273                                         pointIndex += series.Points.Count/5 + 1;
1274                                 }
1275
1276                                 double size = (pointIndex + 1) - current + adjuster;
1277                 
1278                                 return (size != 0) ? size : interval;
1279                         }
1280         
1281                         // Non indexed series
1282                         else
1283                         {
1284                                 DateTime        date = DateTime.FromOADate(current);
1285                                 TimeSpan        span = new TimeSpan(0);
1286
1287                                 if(type == DateTimeIntervalType.Days)
1288                                 {
1289                                         span = TimeSpan.FromDays(interval);
1290                                 }
1291                                 else if(type == DateTimeIntervalType.Hours)
1292                                 {
1293                                         span = TimeSpan.FromHours(interval);
1294                                 }
1295                                 else if(type == DateTimeIntervalType.Milliseconds)
1296                                 {
1297                                         span = TimeSpan.FromMilliseconds(interval);
1298                                 }
1299                                 else if(type == DateTimeIntervalType.Seconds)
1300                                 {
1301                                         span = TimeSpan.FromSeconds(interval);
1302                                 }
1303                                 else if(type == DateTimeIntervalType.Minutes)
1304                                 {
1305                                         span = TimeSpan.FromMinutes(interval);
1306                                 }
1307                                 else if(type == DateTimeIntervalType.Weeks)
1308                                 {
1309                                         span = TimeSpan.FromDays(7.0 * interval);
1310                                 }
1311                                 else if(type == DateTimeIntervalType.Months)
1312                                 {
1313                                         // Special case handling when current date points 
1314                                         // to the last day of the month
1315                                         bool lastMonthDay = false;
1316                                         if(date.Day == DateTime.DaysInMonth(date.Year, date.Month))
1317                                         {
1318                                                 lastMonthDay = true;
1319                                         }
1320
1321                                         // Add specified amount of months
1322                                         date = date.AddMonths((int)Math.Floor(interval));
1323                                         span = TimeSpan.FromDays(30.0 * ( interval - Math.Floor(interval) ));
1324
1325                                         // Check if last month of the day was used
1326                                         if(lastMonthDay && span.Ticks == 0)
1327                                         {
1328                                                 // Make sure the last day of the month is selected
1329                                                 int daysInMobth = DateTime.DaysInMonth(date.Year, date.Month);
1330                                                 date = date.AddDays(daysInMobth - date.Day);
1331                                         }
1332                                 }
1333                                 else if(type == DateTimeIntervalType.Years)
1334                                 {
1335                                         date = date.AddYears((int)Math.Floor(interval));
1336                                         span = TimeSpan.FromDays(365.0 * ( interval - Math.Floor(interval) ));
1337                                 }
1338
1339                                 // Check if an absolute interval size must be returned
1340                                 double result = date.Add(span).ToOADate() - current;
1341                                 if(forceAbsInterval)
1342                                 {
1343                                         result = Math.Abs(result);
1344                                 }
1345                                 return result;
1346                         }
1347                 }
1348
1349                 /// <summary>
1350                 /// Check if series is indexed. IsXValueIndexed flag is set or all X values are zeros.
1351                 /// </summary>
1352                 /// <param name="series">Data series to test.</param>
1353                 /// <returns>True if series is indexed.</returns>
1354                 static internal bool IndexedSeries( Series series)
1355                 {
1356             // X value indexed flag set
1357             if (series.IsXValueIndexed)
1358             {
1359                 return true;
1360             }
1361
1362             if (Utilities.CustomPropertyRegistry.IsXAxisQuantitativeChartTypes.Contains(series.ChartType) && 
1363                 series.IsCustomPropertySet(Utilities.CustomPropertyName.IsXAxisQuantitative))
1364             {
1365                 string attribValue = series[Utilities.CustomPropertyName.IsXAxisQuantitative];
1366                 if (String.Compare(attribValue, "True", StringComparison.OrdinalIgnoreCase) == 0)
1367                 {
1368                     return false;
1369                 }
1370             }
1371
1372             // Check if series has all X values set to zero
1373             return SeriesXValuesZeros(series);
1374                 }
1375
1376                 /// <summary>
1377                 /// Check if all data points in the series have X value set to 0.
1378                 /// </summary>
1379                 /// <param name="series">Data series to check.</param>
1380                 static private bool SeriesXValuesZeros( Series series )
1381                 {
1382                         // Check if X value zeros check was already done
1383                         if(series.xValuesZerosChecked)
1384                         {
1385                                 return series.xValuesZeros;
1386                         }
1387
1388                         // Data point loop
1389             series.xValuesZerosChecked = true;
1390                         series.xValuesZeros = true;
1391                         foreach( DataPoint point in series.Points )
1392                         {
1393                                 if( point.XValue != 0.0 )
1394                                 {
1395                                         // If any data point has value different than 0 return false
1396                                         series.xValuesZeros = false;
1397                                         break;
1398                                 }
1399                         }
1400                         return series.xValuesZeros;
1401                 }
1402
1403                 /// <summary>
1404                 /// Check if any series is indexed. IsXValueIndexed flag is set or all X values are zeros.
1405                 /// </summary>
1406         /// <param name="common">Reference to common chart classes.</param>
1407                 /// <param name="series">Data series names.</param>
1408                 /// <returns>True if any series is indexed.</returns>
1409         static internal bool IndexedSeries(CommonElements common, params string[] series)
1410                 {
1411                         // Data series loop
1412                         bool    zeroXValues = true;
1413             foreach (string ser in series)
1414             {
1415                 Series localSeries = common.DataManager.Series[ser];
1416
1417                 // Check series indexed flag
1418                 if (localSeries.IsXValueIndexed)
1419                 {
1420                     // If flag set in at least one series - all series are indexed
1421                     return true;
1422                 }
1423
1424                 // Check if series has all X values set to zero
1425                 if (zeroXValues && !IndexedSeries(localSeries))
1426                 {
1427                     zeroXValues = false;
1428                 }
1429             }
1430
1431             return zeroXValues;
1432                 }
1433
1434                 /// <summary>
1435                 /// Check if all data points in many series have X value set to 0.
1436                 /// </summary>
1437         /// <param name="common">Reference to common chart classes.</param>
1438                 /// <param name="series">Data series.</param>
1439                 /// <returns>True if all data points have value 0.</returns>
1440         static internal bool SeriesXValuesZeros(CommonElements common, params string[] series)
1441                 {
1442                         // Data series loop
1443                         foreach( string ser in series )
1444                         {
1445                                 // Check one series X values
1446                                 if(!SeriesXValuesZeros(common.DataManager.Series[ ser ]))
1447                                 {
1448                                         return false;
1449                                 }
1450                         }
1451                         return true;
1452                 }
1453
1454                 #endregion
1455     }
1456
1457     #endregion //ChartElement
1458 }