//------------------------------------------------------------- // // Copyright © Microsoft Corporation. All Rights Reserved. // //------------------------------------------------------------- // @owner=alexgor, deliant //================================================================= // File: ChartElement.cs // // Namespace: System.Web.UI.WebControls[Windows.Forms].Charting // // Classes: ChartHelper // // Purpose: The chart element is base class for the big number // of classes. It stores common methods and data. // // Reviewed: GS - August 2, 2002 // AG - August 8, 2002 // AG - Microsoft 16, 2007 // //=================================================================== #region Used namespaces using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Collections; using System.Diagnostics.CodeAnalysis; using System.Collections.Generic; using System.Collections.ObjectModel; #endregion #if Microsoft_CONTROL namespace System.Windows.Forms.DataVisualization.Charting #else namespace System.Web.UI.DataVisualization.Charting #endif { #region Enumerations /// /// An enumeration that specifies a label alignment. /// [ Flags ] public enum LabelAlignmentStyles { /// /// Label is aligned to the top of the data point. /// Top = 1, /// /// Label is aligned to the bottom of the data point. /// Bottom = 2, /// /// Label is aligned to the right of the data point. /// Right = 4, /// /// Label is aligned to the left of the data point. /// Left = 8, /// /// Label is aligned to the top-left corner of the data point. /// TopLeft = 16, /// /// Label is aligned to the top-right corner of the data point. /// TopRight = 32, /// /// Label is aligned to the bottom-left of the data point. /// BottomLeft = 64, /// /// Label is aligned to the bottom-right of the data point. /// BottomRight = 128, /// /// Label is aligned to the center of the data point. /// Center = 256, } /// /// An enumeration of chart types. /// public enum SeriesChartType { /// /// Point chart type. /// Point, /// /// FastPoint chart type. /// FastPoint, /// /// Bubble chart type. /// Bubble, /// /// Line chart type. /// Line, /// /// Spline chart type. /// Spline, /// /// StepLine chart type. /// StepLine, /// /// FastLine chart type. /// FastLine, /// /// Bar chart type. /// Bar, /// /// Stacked bar chart type. /// StackedBar, /// /// Hundred percent stacked bar chart type. /// StackedBar100, /// /// Column chart type. /// Column, /// /// Stacked column chart type. /// StackedColumn, /// /// Hundred percent stacked column chart type. /// StackedColumn100, /// /// Area chart type. /// Area, /// /// Spline area chart type. /// SplineArea, /// /// Stacked area chart type. /// StackedArea, /// /// Hundred percent stacked area chart type. /// StackedArea100, /// /// Pie chart type. /// Pie, /// /// Doughnut chart type. /// Doughnut, /// /// Stock chart type. /// Stock, /// /// CandleStick chart type. /// Candlestick, /// /// Range chart type. /// Range, /// /// Spline range chart type. /// SplineRange, /// /// RangeBar chart type. /// RangeBar, /// /// Range column chart type. /// RangeColumn, /// /// Radar chart type. /// Radar, /// /// Polar chart type. /// Polar, /// /// Error bar chart type. /// ErrorBar, /// /// Box plot chart type. /// BoxPlot, /// /// Renko chart type. /// [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Renko")] Renko, /// /// ThreeLineBreak chart type. /// ThreeLineBreak, /// /// Kagi chart type. /// [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Kagi")] Kagi, /// /// PointAndFigure chart type. /// PointAndFigure, /// /// Funnel chart type. /// Funnel, /// /// Pyramid chart type. /// Pyramid, } /// /// Axis Arrow orientation /// internal enum ArrowOrientation { /// /// Arrow direction is Right - Left /// Left, /// /// Arrow direction is Left - Right /// Right, /// /// Arrow direction is Bottom - Top /// Top, /// /// Arrow direction is Top - Bottom /// Bottom } /// /// An enumeration of image alignment. /// public enum ChartImageAlignmentStyle { /// /// The mage is aligned to the top left corner of the chart element. /// TopLeft, /// /// The image is aligned to the top boundary of the chart element. /// Top, /// /// The image is aligned to the top right corner of the chart element. /// TopRight, /// /// The image is aligned to the right boundary of the chart element. /// Right, /// /// The image is aligned to the bottom right corner of the chart element. /// BottomRight, /// /// The image is aligned to the bottom boundary of the chart element. /// Bottom, /// /// The image is aligned to the bottom left corner of the chart element. /// BottomLeft, /// /// The image is aligned to the left boundary of the chart element. /// Left, /// /// The image is aligned in the center of the chart element. /// Center }; /// /// An enumeration that specifies a background image drawing mode. /// public enum ChartImageWrapMode { /// /// Background image is scaled to fit the entire chart element. /// Scaled = WrapMode.Clamp, /// /// Background image is tiled to fit the entire chart element. /// Tile = WrapMode.Tile, /// /// Every other tiled image is reversed around the X-axis. /// TileFlipX = WrapMode.TileFlipX, /// /// Every other tiled image is reversed around the X-axis and Y-axis. /// TileFlipXY = WrapMode.TileFlipXY, /// /// Every other tiled image is reversed around the Y-axis. /// TileFlipY = WrapMode.TileFlipY, /// /// Background image is not scaled. /// [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Unscaled")] Unscaled = 100 }; /// /// An enumeration that specifies the state of an axis. /// public enum AxisEnabled { /// /// The axis is only enabled if it used to plot a Series. /// Auto, /// /// The axis is always enabled. /// True, /// /// The axis is never enabled. /// False }; /// /// An enumeration of units of measurement of an interval. /// public enum DateTimeIntervalType { /// /// Automatically determined by the Chart control. /// Auto, /// /// The interval is numerical. /// Number, /// /// The interval is years. /// Years, /// /// The interval is months. /// Months, /// /// The interval is weeks. /// Weeks, /// /// The interval is days. /// Days, /// /// The interval is hours. /// Hours, /// /// The interval is minutes. /// Minutes, /// /// The interval is seconds. /// Seconds, /// /// The interval is milliseconds. /// Milliseconds, /// /// The interval type is not defined. /// NotSet, } /// /// An enumeration that specifies value types for various chart properties /// public enum ChartValueType { /// /// Property type is set automatically by the Chart control. /// Auto, /// /// Double value. /// Double, /// /// Single value. /// Single, /// /// Int32 value. /// Int32, /// /// Int64 value. /// Int64, /// /// UInt32 value. /// [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Justification = "These names are patterned after the standard CLR types for consistency")] UInt32, /// /// UInt64 value. /// [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Justification = "These names are patterned after the standard CLR types for consistency")] UInt64, /// /// String value. /// String, /// /// DateTime value. /// DateTime, /// /// Date portion of the DateTime value. /// Date, /// /// Time portion of the DateTime value. /// Time, /// /// DateTime with offset /// DateTimeOffset }; /// /// An enumeration that specifies a hatching style. /// public enum ChartHatchStyle { /// /// No hatching style. /// None, /// /// Backward diagonal style. /// BackwardDiagonal, /// /// Cross style. /// Cross, /// /// Dark downward diagonal style. /// DarkDownwardDiagonal, /// /// Dark horizontal style. /// DarkHorizontal, /// /// Dark upward diagonal style. /// DarkUpwardDiagonal, /// /// Dark vertical style. /// DarkVertical, /// /// Dashed downward diagonal style. /// DashedDownwardDiagonal, /// /// Dashed horizontal style. /// DashedHorizontal, /// /// Dashed upward diagonal style. /// DashedUpwardDiagonal, /// /// Dashed vertical style. /// DashedVertical, /// /// Diagonal brick style. /// DiagonalBrick, /// /// Diagonal cross style. /// DiagonalCross, /// /// Divot style. /// Divot, /// /// Dotted diamond style. /// DottedDiamond, /// /// Dotted grid style. /// DottedGrid, /// /// Forward diagonal style. /// ForwardDiagonal, /// /// Horizontal style. /// Horizontal, /// /// Horizontal brick style. /// HorizontalBrick, /// /// Large checker board style. /// [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "CheckerBoard")] LargeCheckerBoard, /// /// Large confetti style. /// LargeConfetti, /// /// Large grid style. /// LargeGrid, /// /// Light downward diagonal style. /// LightDownwardDiagonal, /// /// Light horizontal style. /// LightHorizontal, /// /// Light upward diagonal style. /// LightUpwardDiagonal, /// /// Light vertical style. /// LightVertical, /// /// Narrow horizontal style. /// NarrowHorizontal, /// /// Narrow vertical style. /// NarrowVertical, /// /// Outlined diamond style. /// OutlinedDiamond, /// /// Percent05 style. /// Percent05, /// /// Percent10 style. /// Percent10, /// /// Percent20 style. /// Percent20, /// /// Percent25 style. /// Percent25, /// /// Percent30 style. /// Percent30, /// /// Percent40 style. /// Percent40, /// /// Percent50 style. /// Percent50, /// /// Percent60 style. /// Percent60, /// /// Percent70 style. /// Percent70, /// /// Percent75 style. /// Percent75, /// /// Percent80 style. /// Percent80, /// /// Percent90 style. /// Percent90, /// /// Plaid style. /// Plaid, /// /// Shingle style. /// Shingle, /// /// Small checker board style. /// [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "CheckerBoard")] SmallCheckerBoard, /// /// Small confetti style. /// SmallConfetti, /// /// Small grid style. /// SmallGrid, /// /// Solid diamond style. /// SolidDiamond, /// /// Sphere style. /// Sphere, /// /// Trellis style. /// Trellis, /// /// Vertical style. /// Vertical, /// /// Wave style. /// Wave, /// /// Weave style. /// Weave, /// /// Wide downward diagonal style. /// WideDownwardDiagonal, /// /// Wide upward diagonal style. /// WideUpwardDiagonal, /// /// ZigZag style. /// [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "ZigZag")] [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Zig")] [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Zag")] ZigZag }; /// /// An enumeration that specifies the level of anti-aliasing quality. /// public enum TextAntiAliasingQuality { /// /// Normal anti-aliasing quality. /// Normal, /// /// High anti-aliasing quality. /// High, /// /// System default anti-aliasing quality. /// SystemDefault } /// /// An enumeration of anti-aliasing flags. /// [Flags] public enum AntiAliasingStyles { /// /// No anti-aliasing. /// None = 0, /// /// Use anti-aliasing when drawing text. /// Text = 1, /// /// Use anti-aliasing when drawing grahics primitives (e.g. lines, rectangle) /// Graphics = 2, /// /// Use anti-alias for everything. /// All = Text | Graphics }; /// /// An enumeration of marker styles. /// public enum MarkerStyle { /// /// No marker is displayed for the series/data point. /// None = 0, /// /// A square marker is displayed. /// Square = 1, /// /// A circle marker is displayed. /// Circle = 2, /// /// A diamond-shaped marker is displayed. /// Diamond = 3, /// /// A triangular marker is displayed. /// Triangle = 4, /// /// A cross-shaped marker is displayed. /// Cross = 5, /// /// A 4-point star-shaped marker is displayed. /// Star4 = 6, /// /// A 5-point star-shaped marker is displayed. /// Star5 = 7, /// /// A 6-point star-shaped marker is displayed. /// Star6 = 8, /// /// A 10-point star-shaped marker is displayed. /// Star10 = 9 }; /// /// An enumeration of gradient styles. /// public enum GradientStyle { /// /// No gradient is used. /// None, /// /// Gradient is applied from left to right. /// LeftRight, /// /// Gradient is applied from top to bottom. /// TopBottom, /// /// Gradient is applied from the center outwards. /// Center, /// /// Gradient is applied diagonally from left to right. /// DiagonalLeft, /// /// Gradient is applied diagonally from right to left. /// DiagonalRight, /// /// Gradient is applied horizontally from the center outwards. /// HorizontalCenter, /// /// Gradient is applied vertically from the center outwards. /// VerticalCenter }; #endregion #region ChartElement /// /// Common chart helper methods used across different chart elements. /// internal class ChartHelper { #region Fields /// /// Maximum number of grid lines per Axis /// internal const int MaxNumOfGridlines = 10000; #endregion // Fields #region Constructor /// /// Private constructor to avoid instantiating the class /// private ChartHelper() { } #endregion // Constructor #region Methods /// /// Adjust the beginnin of the first interval depending on the type and size. /// /// Original start point. /// Interval size. /// AxisName of the interval (Month, Year, ...). /// Adjusted interval start position as double. internal static double AlignIntervalStart(double start, double intervalSize, DateTimeIntervalType type) { return AlignIntervalStart(start, intervalSize, type, null); } /// /// Adjust the beginnin of the first interval depending on the type and size. /// /// Original start point. /// Interval size. /// AxisName of the interval (Month, Year, ...). /// First series connected to the axis. /// Adjusted interval start position as double. internal static double AlignIntervalStart(double start, double intervalSize, DateTimeIntervalType type, Series series) { return AlignIntervalStart( start, intervalSize, type, series, true ); } /// /// Adjust the beginnin of the first interval depending on the type and size. /// /// Original start point. /// Interval size. /// AxisName of the interval (Month, Year, ...). /// First series connected to the axis. /// Interval is used for major gridlines or tickmarks. /// Adjusted interval start position as double. internal static double AlignIntervalStart(double start, double intervalSize, DateTimeIntervalType type, Series series, bool majorInterval) { // Special case for indexed series if(series != null && series.IsXValueIndexed) { if(type == DateTimeIntervalType.Auto || type == DateTimeIntervalType.Number) { if( majorInterval ) { return 1; } else { return 0; } } return -(series.Points.Count + 1); } // Non indexed series else { // Do not adjust start position for these interval type if(type == DateTimeIntervalType.Auto || type == DateTimeIntervalType.Number) { return start; } // Get the beginning of the interval depending on type DateTime newStartDate = DateTime.FromOADate(start); // Adjust the months interval depending on size if(intervalSize > 0.0 && intervalSize != 1.0) { if(type == DateTimeIntervalType.Months && intervalSize <= 12.0 && intervalSize > 1) { // Make sure that the beginning is aligned correctly for cases // like quarters and half years DateTime resultDate = newStartDate; DateTime sizeAdjustedDate = new DateTime(newStartDate.Year, 1, 1, 0, 0, 0); while(sizeAdjustedDate < newStartDate) { resultDate = sizeAdjustedDate; sizeAdjustedDate = sizeAdjustedDate.AddMonths((int)intervalSize); } newStartDate = resultDate; return newStartDate.ToOADate(); } } // Check interval type switch(type) { case(DateTimeIntervalType.Years): int year = (int)((int)(newStartDate.Year / intervalSize) * intervalSize); if(year <= 0) { year = 1; } newStartDate = new DateTime(year, 1, 1, 0, 0, 0); break; case(DateTimeIntervalType.Months): int month = (int)((int)(newStartDate.Month / intervalSize) * intervalSize); if(month <= 0) { month = 1; } newStartDate = new DateTime(newStartDate.Year, month, 1, 0, 0, 0); break; case(DateTimeIntervalType.Days): int day = (int)((int)(newStartDate.Day / intervalSize) * intervalSize); if(day <= 0) { day = 1; } newStartDate = new DateTime(newStartDate.Year, newStartDate.Month, day, 0, 0, 0); break; case(DateTimeIntervalType.Hours): int hour = (int)((int)(newStartDate.Hour / intervalSize) * intervalSize); newStartDate = new DateTime(newStartDate.Year, newStartDate.Month, newStartDate.Day, hour, 0, 0); break; case(DateTimeIntervalType.Minutes): int minute = (int)((int)(newStartDate.Minute / intervalSize) * intervalSize); newStartDate = new DateTime(newStartDate.Year, newStartDate.Month, newStartDate.Day, newStartDate.Hour, minute, 0); break; case(DateTimeIntervalType.Seconds): int second = (int)((int)(newStartDate.Second / intervalSize) * intervalSize); newStartDate = new DateTime(newStartDate.Year, newStartDate.Month, newStartDate.Day, newStartDate.Hour, newStartDate.Minute, second, 0); break; case(DateTimeIntervalType.Milliseconds): int milliseconds = (int)((int)(newStartDate.Millisecond / intervalSize) * intervalSize); newStartDate = new DateTime(newStartDate.Year, newStartDate.Month, newStartDate.Day, newStartDate.Hour, newStartDate.Minute, newStartDate.Second, milliseconds); break; case(DateTimeIntervalType.Weeks): // NOTE: Code below was changed to fix issue #5962 // Elements that have interval set to weeks should be aligned to the // nearest Monday no matter how many weeks is the interval. //newStartDate = newStartDate.AddDays(-((int)newStartDate.DayOfWeek * intervalSize)); newStartDate = newStartDate.AddDays(-((int)newStartDate.DayOfWeek)); newStartDate = new DateTime(newStartDate.Year, newStartDate.Month, newStartDate.Day, 0, 0, 0); break; } return newStartDate.ToOADate(); } } /// /// Gets interval size as double number. /// /// Current value. /// Interval size. /// AxisName of the interval (Month, Year, ...). /// Interval size as double. internal static double GetIntervalSize(double current, double interval, DateTimeIntervalType type) { return GetIntervalSize( current, interval, type, null, 0, DateTimeIntervalType.Number, true, true); } /// /// Gets interval size as double number. /// /// Current value. /// Interval size. /// AxisName of the interval (Month, Year, ...). /// First series connected to the axis. /// Offset size. /// Offset type(Month, Year, ...). /// Force Integer indexed /// Interval size as double. internal static double GetIntervalSize( double current, double interval, DateTimeIntervalType type, Series series, double intervalOffset, DateTimeIntervalType intervalOffsetType, bool forceIntIndex) { return GetIntervalSize( current, interval, type, series, intervalOffset, intervalOffsetType, forceIntIndex, true); } /// /// Gets interval size as double number. /// /// Current value. /// Interval size. /// AxisName of the interval (Month, Year, ...). /// First series connected to the axis. /// Offset size. /// Offset type(Month, Year, ...). /// Force Integer indexed /// Force Integer indexed /// Interval size as double. internal static double GetIntervalSize( double current, double interval, DateTimeIntervalType type, Series series, double intervalOffset, DateTimeIntervalType intervalOffsetType, bool forceIntIndex, bool forceAbsInterval) { // AxisName is not date. if( type == DateTimeIntervalType.Number || type == DateTimeIntervalType.Auto ) { return interval; } // Special case for indexed series if(series != null && series.IsXValueIndexed) { // Check point index int pointIndex = (int)Math.Ceiling(current - 1); if(pointIndex < 0) { pointIndex = 0; } if(pointIndex >= series.Points.Count || series.Points.Count <= 1) { return interval; } // Get starting and ending values of the closest interval double adjuster = 0; double xValue = series.Points[pointIndex].XValue; xValue = AlignIntervalStart(xValue, 1, type, null); double xEndValue = xValue + GetIntervalSize(xValue, interval, type); xEndValue += GetIntervalSize(xEndValue, intervalOffset, intervalOffsetType); xValue += GetIntervalSize(xValue, intervalOffset, intervalOffsetType); if(intervalOffset < 0) { xValue = xValue + GetIntervalSize(xValue, interval, type); xEndValue = xEndValue + GetIntervalSize(xEndValue, interval, type); } // The first point in the series if(pointIndex == 0 && current < 0) { // Round the first point value depending on the interval type DateTime dateValue = DateTime.FromOADate(series.Points[pointIndex].XValue); DateTime roundedDateValue = dateValue; switch(type) { case(DateTimeIntervalType.Years): // Ignore hours,... roundedDateValue = new DateTime(dateValue.Year, dateValue.Month, dateValue.Day, 0, 0, 0); break; case(DateTimeIntervalType.Months): // Ignore hours,... roundedDateValue = new DateTime(dateValue.Year, dateValue.Month, dateValue.Day, 0, 0, 0); break; case(DateTimeIntervalType.Days): // Ignore hours,... roundedDateValue = new DateTime(dateValue.Year, dateValue.Month, dateValue.Day, 0, 0, 0); break; case(DateTimeIntervalType.Hours): // roundedDateValue = new DateTime(dateValue.Year, dateValue.Month, dateValue.Day, dateValue.Hour, dateValue.Minute, 0); break; case(DateTimeIntervalType.Minutes): roundedDateValue = new DateTime(dateValue.Year, dateValue.Month, dateValue.Day, dateValue.Hour, dateValue.Minute, dateValue.Second); break; case(DateTimeIntervalType.Seconds): roundedDateValue = new DateTime(dateValue.Year, dateValue.Month, dateValue.Day, dateValue.Hour, dateValue.Minute, dateValue.Second, 0); break; case(DateTimeIntervalType.Weeks): roundedDateValue = new DateTime(dateValue.Year, dateValue.Month, dateValue.Day, 0, 0, 0); break; } // The first point value is exactly on the interval boundaries if(roundedDateValue.ToOADate() == xValue || roundedDateValue.ToOADate() == xEndValue) { return - current + 1; } } // Adjuster of 0.5 means that position should be between points ++pointIndex; while(pointIndex < series.Points.Count) { if(series.Points[pointIndex].XValue >= xEndValue) { if(series.Points[pointIndex].XValue > xEndValue && !forceIntIndex) { adjuster = -0.5; } break; } ++pointIndex; } // If last point outside of the max series index if(pointIndex == series.Points.Count) { pointIndex += series.Points.Count/5 + 1; } double size = (pointIndex + 1) - current + adjuster; return (size != 0) ? size : interval; } // Non indexed series else { DateTime date = DateTime.FromOADate(current); TimeSpan span = new TimeSpan(0); if(type == DateTimeIntervalType.Days) { span = TimeSpan.FromDays(interval); } else if(type == DateTimeIntervalType.Hours) { span = TimeSpan.FromHours(interval); } else if(type == DateTimeIntervalType.Milliseconds) { span = TimeSpan.FromMilliseconds(interval); } else if(type == DateTimeIntervalType.Seconds) { span = TimeSpan.FromSeconds(interval); } else if(type == DateTimeIntervalType.Minutes) { span = TimeSpan.FromMinutes(interval); } else if(type == DateTimeIntervalType.Weeks) { span = TimeSpan.FromDays(7.0 * interval); } else if(type == DateTimeIntervalType.Months) { // Special case handling when current date points // to the last day of the month bool lastMonthDay = false; if(date.Day == DateTime.DaysInMonth(date.Year, date.Month)) { lastMonthDay = true; } // Add specified amount of months date = date.AddMonths((int)Math.Floor(interval)); span = TimeSpan.FromDays(30.0 * ( interval - Math.Floor(interval) )); // Check if last month of the day was used if(lastMonthDay && span.Ticks == 0) { // Make sure the last day of the month is selected int daysInMobth = DateTime.DaysInMonth(date.Year, date.Month); date = date.AddDays(daysInMobth - date.Day); } } else if(type == DateTimeIntervalType.Years) { date = date.AddYears((int)Math.Floor(interval)); span = TimeSpan.FromDays(365.0 * ( interval - Math.Floor(interval) )); } // Check if an absolute interval size must be returned double result = date.Add(span).ToOADate() - current; if(forceAbsInterval) { result = Math.Abs(result); } return result; } } /// /// Check if series is indexed. IsXValueIndexed flag is set or all X values are zeros. /// /// Data series to test. /// True if series is indexed. static internal bool IndexedSeries( Series series) { // X value indexed flag set if (series.IsXValueIndexed) { return true; } if (Utilities.CustomPropertyRegistry.IsXAxisQuantitativeChartTypes.Contains(series.ChartType) && series.IsCustomPropertySet(Utilities.CustomPropertyName.IsXAxisQuantitative)) { string attribValue = series[Utilities.CustomPropertyName.IsXAxisQuantitative]; if (String.Compare(attribValue, "True", StringComparison.OrdinalIgnoreCase) == 0) { return false; } } // Check if series has all X values set to zero return SeriesXValuesZeros(series); } /// /// Check if all data points in the series have X value set to 0. /// /// Data series to check. static private bool SeriesXValuesZeros( Series series ) { // Check if X value zeros check was already done if(series.xValuesZerosChecked) { return series.xValuesZeros; } // Data point loop series.xValuesZerosChecked = true; series.xValuesZeros = true; foreach( DataPoint point in series.Points ) { if( point.XValue != 0.0 ) { // If any data point has value different than 0 return false series.xValuesZeros = false; break; } } return series.xValuesZeros; } /// /// Check if any series is indexed. IsXValueIndexed flag is set or all X values are zeros. /// /// Reference to common chart classes. /// Data series names. /// True if any series is indexed. static internal bool IndexedSeries(CommonElements common, params string[] series) { // Data series loop bool zeroXValues = true; foreach (string ser in series) { Series localSeries = common.DataManager.Series[ser]; // Check series indexed flag if (localSeries.IsXValueIndexed) { // If flag set in at least one series - all series are indexed return true; } // Check if series has all X values set to zero if (zeroXValues && !IndexedSeries(localSeries)) { zeroXValues = false; } } return zeroXValues; } /// /// Check if all data points in many series have X value set to 0. /// /// Reference to common chart classes. /// Data series. /// True if all data points have value 0. static internal bool SeriesXValuesZeros(CommonElements common, params string[] series) { // Data series loop foreach( string ser in series ) { // Check one series X values if(!SeriesXValuesZeros(common.DataManager.Series[ ser ])) { return false; } } return true; } #endregion } #endregion //ChartElement }