536cd135cc
Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
1459 lines
36 KiB
C#
1459 lines
36 KiB
C#
//-------------------------------------------------------------
|
||
// <copyright company=’Microsoft Corporation’>
|
||
// Copyright © Microsoft Corporation. All Rights Reserved.
|
||
// </copyright>
|
||
//-------------------------------------------------------------
|
||
// @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
|
||
|
||
/// <summary>
|
||
/// An enumeration that specifies a label alignment.
|
||
/// </summary>
|
||
[
|
||
Flags
|
||
]
|
||
public enum LabelAlignmentStyles
|
||
{
|
||
/// <summary>
|
||
/// Label is aligned to the top of the data point.
|
||
/// </summary>
|
||
Top = 1,
|
||
/// <summary>
|
||
/// Label is aligned to the bottom of the data point.
|
||
/// </summary>
|
||
Bottom = 2,
|
||
/// <summary>
|
||
/// Label is aligned to the right of the data point.
|
||
/// </summary>
|
||
Right = 4,
|
||
/// <summary>
|
||
/// Label is aligned to the left of the data point.
|
||
/// </summary>
|
||
Left = 8,
|
||
/// <summary>
|
||
/// Label is aligned to the top-left corner of the data point.
|
||
/// </summary>
|
||
TopLeft = 16,
|
||
/// <summary>
|
||
/// Label is aligned to the top-right corner of the data point.
|
||
/// </summary>
|
||
TopRight = 32,
|
||
/// <summary>
|
||
/// Label is aligned to the bottom-left of the data point.
|
||
/// </summary>
|
||
BottomLeft = 64,
|
||
/// <summary>
|
||
/// Label is aligned to the bottom-right of the data point.
|
||
/// </summary>
|
||
BottomRight = 128,
|
||
/// <summary>
|
||
/// Label is aligned to the center of the data point.
|
||
/// </summary>
|
||
Center = 256,
|
||
}
|
||
|
||
/// <summary>
|
||
/// An enumeration of chart types.
|
||
/// </summary>
|
||
public enum SeriesChartType
|
||
{
|
||
/// <summary>
|
||
/// Point chart type.
|
||
/// </summary>
|
||
Point,
|
||
|
||
/// <summary>
|
||
/// FastPoint chart type.
|
||
/// </summary>
|
||
FastPoint,
|
||
|
||
/// <summary>
|
||
/// Bubble chart type.
|
||
/// </summary>
|
||
Bubble,
|
||
/// <summary>
|
||
/// Line chart type.
|
||
/// </summary>
|
||
Line,
|
||
/// <summary>
|
||
/// Spline chart type.
|
||
/// </summary>
|
||
Spline,
|
||
/// <summary>
|
||
/// StepLine chart type.
|
||
/// </summary>
|
||
StepLine,
|
||
|
||
/// <summary>
|
||
/// FastLine chart type.
|
||
/// </summary>
|
||
FastLine,
|
||
|
||
/// <summary>
|
||
/// Bar chart type.
|
||
/// </summary>
|
||
Bar,
|
||
/// <summary>
|
||
/// Stacked bar chart type.
|
||
/// </summary>
|
||
StackedBar,
|
||
/// <summary>
|
||
/// Hundred percent stacked bar chart type.
|
||
/// </summary>
|
||
StackedBar100,
|
||
/// <summary>
|
||
/// Column chart type.
|
||
/// </summary>
|
||
Column,
|
||
/// <summary>
|
||
/// Stacked column chart type.
|
||
/// </summary>
|
||
StackedColumn,
|
||
/// <summary>
|
||
/// Hundred percent stacked column chart type.
|
||
/// </summary>
|
||
StackedColumn100,
|
||
/// <summary>
|
||
/// Area chart type.
|
||
/// </summary>
|
||
Area,
|
||
/// <summary>
|
||
/// Spline area chart type.
|
||
/// </summary>
|
||
SplineArea,
|
||
/// <summary>
|
||
/// Stacked area chart type.
|
||
/// </summary>
|
||
StackedArea,
|
||
/// <summary>
|
||
/// Hundred percent stacked area chart type.
|
||
/// </summary>
|
||
StackedArea100,
|
||
/// <summary>
|
||
/// Pie chart type.
|
||
/// </summary>
|
||
Pie,
|
||
/// <summary>
|
||
/// Doughnut chart type.
|
||
/// </summary>
|
||
Doughnut,
|
||
/// <summary>
|
||
/// Stock chart type.
|
||
/// </summary>
|
||
Stock,
|
||
/// <summary>
|
||
/// CandleStick chart type.
|
||
/// </summary>
|
||
Candlestick,
|
||
/// <summary>
|
||
/// Range chart type.
|
||
/// </summary>
|
||
Range,
|
||
/// <summary>
|
||
/// Spline range chart type.
|
||
/// </summary>
|
||
SplineRange,
|
||
/// <summary>
|
||
/// RangeBar chart type.
|
||
/// </summary>
|
||
RangeBar,
|
||
/// <summary>
|
||
/// Range column chart type.
|
||
/// </summary>
|
||
RangeColumn,
|
||
/// <summary>
|
||
/// Radar chart type.
|
||
/// </summary>
|
||
Radar,
|
||
/// <summary>
|
||
/// Polar chart type.
|
||
/// </summary>
|
||
Polar,
|
||
/// <summary>
|
||
/// Error bar chart type.
|
||
/// </summary>
|
||
ErrorBar,
|
||
/// <summary>
|
||
/// Box plot chart type.
|
||
/// </summary>
|
||
BoxPlot,
|
||
/// <summary>
|
||
/// Renko chart type.
|
||
/// </summary>
|
||
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Renko")]
|
||
Renko,
|
||
/// <summary>
|
||
/// ThreeLineBreak chart type.
|
||
/// </summary>
|
||
ThreeLineBreak,
|
||
/// <summary>
|
||
/// Kagi chart type.
|
||
/// </summary>
|
||
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Kagi")]
|
||
Kagi,
|
||
/// <summary>
|
||
/// PointAndFigure chart type.
|
||
/// </summary>
|
||
PointAndFigure,
|
||
/// <summary>
|
||
/// Funnel chart type.
|
||
/// </summary>
|
||
Funnel,
|
||
/// <summary>
|
||
/// Pyramid chart type.
|
||
/// </summary>
|
||
Pyramid,
|
||
}
|
||
|
||
/// <summary>
|
||
/// Axis Arrow orientation
|
||
/// </summary>
|
||
internal enum ArrowOrientation
|
||
{
|
||
/// <summary>
|
||
/// Arrow direction is Right - Left
|
||
/// </summary>
|
||
Left,
|
||
/// <summary>
|
||
/// Arrow direction is Left - Right
|
||
/// </summary>
|
||
Right,
|
||
/// <summary>
|
||
/// Arrow direction is Bottom - Top
|
||
/// </summary>
|
||
Top,
|
||
/// <summary>
|
||
/// Arrow direction is Top - Bottom
|
||
/// </summary>
|
||
Bottom
|
||
}
|
||
|
||
/// <summary>
|
||
/// An enumeration of image alignment.
|
||
/// </summary>
|
||
public enum ChartImageAlignmentStyle
|
||
{
|
||
/// <summary>
|
||
/// The mage is aligned to the top left corner of the chart element.
|
||
/// </summary>
|
||
TopLeft,
|
||
/// <summary>
|
||
/// The image is aligned to the top boundary of the chart element.
|
||
/// </summary>
|
||
Top,
|
||
/// <summary>
|
||
/// The image is aligned to the top right corner of the chart element.
|
||
/// </summary>
|
||
TopRight,
|
||
/// <summary>
|
||
/// The image is aligned to the right boundary of the chart element.
|
||
/// </summary>
|
||
Right,
|
||
/// <summary>
|
||
/// The image is aligned to the bottom right corner of the chart element.
|
||
/// </summary>
|
||
BottomRight,
|
||
/// <summary>
|
||
/// The image is aligned to the bottom boundary of the chart element.
|
||
/// </summary>
|
||
Bottom,
|
||
/// <summary>
|
||
/// The image is aligned to the bottom left corner of the chart element.
|
||
/// </summary>
|
||
BottomLeft,
|
||
/// <summary>
|
||
/// The image is aligned to the left boundary of the chart element.
|
||
/// </summary>
|
||
Left,
|
||
/// <summary>
|
||
/// The image is aligned in the center of the chart element.
|
||
/// </summary>
|
||
Center
|
||
};
|
||
|
||
/// <summary>
|
||
/// An enumeration that specifies a background image drawing mode.
|
||
/// </summary>
|
||
public enum ChartImageWrapMode
|
||
{
|
||
/// <summary>
|
||
/// Background image is scaled to fit the entire chart element.
|
||
/// </summary>
|
||
Scaled = WrapMode.Clamp,
|
||
|
||
/// <summary>
|
||
/// Background image is tiled to fit the entire chart element.
|
||
/// </summary>
|
||
Tile = WrapMode.Tile,
|
||
|
||
/// <summary>
|
||
/// Every other tiled image is reversed around the X-axis.
|
||
/// </summary>
|
||
TileFlipX = WrapMode.TileFlipX,
|
||
|
||
/// <summary>
|
||
/// Every other tiled image is reversed around the X-axis and Y-axis.
|
||
/// </summary>
|
||
TileFlipXY = WrapMode.TileFlipXY,
|
||
|
||
/// <summary>
|
||
/// Every other tiled image is reversed around the Y-axis.
|
||
/// </summary>
|
||
TileFlipY = WrapMode.TileFlipY,
|
||
|
||
/// <summary>
|
||
/// Background image is not scaled.
|
||
/// </summary>
|
||
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Unscaled")]
|
||
Unscaled = 100
|
||
};
|
||
|
||
/// <summary>
|
||
/// An enumeration that specifies the state of an axis.
|
||
/// </summary>
|
||
public enum AxisEnabled
|
||
{
|
||
/// <summary>
|
||
/// The axis is only enabled if it used to plot a Series.
|
||
/// </summary>
|
||
Auto,
|
||
|
||
/// <summary>
|
||
/// The axis is always enabled.
|
||
/// </summary>
|
||
True,
|
||
|
||
/// <summary>
|
||
/// The axis is never enabled.
|
||
/// </summary>
|
||
False
|
||
|
||
};
|
||
|
||
/// <summary>
|
||
/// An enumeration of units of measurement of an interval.
|
||
/// </summary>
|
||
public enum DateTimeIntervalType
|
||
{
|
||
/// <summary>
|
||
/// Automatically determined by the Chart control.
|
||
/// </summary>
|
||
Auto,
|
||
|
||
/// <summary>
|
||
/// The interval is numerical.
|
||
/// </summary>
|
||
Number,
|
||
|
||
/// <summary>
|
||
/// The interval is years.
|
||
/// </summary>
|
||
Years,
|
||
|
||
/// <summary>
|
||
/// The interval is months.
|
||
/// </summary>
|
||
Months,
|
||
|
||
/// <summary>
|
||
/// The interval is weeks.
|
||
/// </summary>
|
||
Weeks,
|
||
|
||
/// <summary>
|
||
/// The interval is days.
|
||
/// </summary>
|
||
Days,
|
||
|
||
/// <summary>
|
||
/// The interval is hours.
|
||
/// </summary>
|
||
Hours,
|
||
|
||
/// <summary>
|
||
/// The interval is minutes.
|
||
/// </summary>
|
||
Minutes,
|
||
|
||
/// <summary>
|
||
/// The interval is seconds.
|
||
/// </summary>
|
||
Seconds,
|
||
|
||
/// <summary>
|
||
/// The interval is milliseconds.
|
||
/// </summary>
|
||
Milliseconds,
|
||
|
||
/// <summary>
|
||
/// The interval type is not defined.
|
||
/// </summary>
|
||
NotSet,
|
||
}
|
||
|
||
/// <summary>
|
||
/// An enumeration that specifies value types for various chart properties
|
||
/// </summary>
|
||
public enum ChartValueType
|
||
{
|
||
/// <summary>
|
||
/// Property type is set automatically by the Chart control.
|
||
/// </summary>
|
||
Auto,
|
||
|
||
/// <summary>
|
||
/// Double value.
|
||
/// </summary>
|
||
Double,
|
||
|
||
/// <summary>
|
||
/// Single value.
|
||
/// </summary>
|
||
Single,
|
||
|
||
/// <summary>
|
||
/// Int32 value.
|
||
/// </summary>
|
||
Int32,
|
||
|
||
/// <summary>
|
||
/// Int64 value.
|
||
/// </summary>
|
||
Int64,
|
||
|
||
/// <summary>
|
||
/// UInt32 value.
|
||
/// </summary>
|
||
[SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly",
|
||
Justification = "These names are patterned after the standard CLR types for consistency")]
|
||
UInt32,
|
||
|
||
/// <summary>
|
||
/// UInt64 value.
|
||
/// </summary>
|
||
[SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly",
|
||
Justification = "These names are patterned after the standard CLR types for consistency")]
|
||
UInt64,
|
||
|
||
/// <summary>
|
||
/// String value.
|
||
/// </summary>
|
||
String,
|
||
|
||
/// <summary>
|
||
/// DateTime value.
|
||
/// </summary>
|
||
DateTime,
|
||
|
||
/// <summary>
|
||
/// Date portion of the DateTime value.
|
||
/// </summary>
|
||
Date,
|
||
|
||
/// <summary>
|
||
/// Time portion of the DateTime value.
|
||
/// </summary>
|
||
Time,
|
||
|
||
/// <summary>
|
||
/// DateTime with offset
|
||
/// </summary>
|
||
DateTimeOffset
|
||
};
|
||
|
||
/// <summary>
|
||
/// An enumeration that specifies a hatching style.
|
||
/// </summary>
|
||
public enum ChartHatchStyle
|
||
{
|
||
/// <summary>
|
||
/// No hatching style.
|
||
/// </summary>
|
||
None,
|
||
/// <summary>
|
||
/// Backward diagonal style.
|
||
/// </summary>
|
||
BackwardDiagonal,
|
||
/// <summary>
|
||
/// Cross style.
|
||
/// </summary>
|
||
Cross,
|
||
/// <summary>
|
||
/// Dark downward diagonal style.
|
||
/// </summary>
|
||
DarkDownwardDiagonal,
|
||
/// <summary>
|
||
/// Dark horizontal style.
|
||
/// </summary>
|
||
DarkHorizontal,
|
||
/// <summary>
|
||
/// Dark upward diagonal style.
|
||
/// </summary>
|
||
DarkUpwardDiagonal,
|
||
/// <summary>
|
||
/// Dark vertical style.
|
||
/// </summary>
|
||
DarkVertical,
|
||
/// <summary>
|
||
/// Dashed downward diagonal style.
|
||
/// </summary>
|
||
DashedDownwardDiagonal,
|
||
/// <summary>
|
||
/// Dashed horizontal style.
|
||
/// </summary>
|
||
DashedHorizontal,
|
||
/// <summary>
|
||
/// Dashed upward diagonal style.
|
||
/// </summary>
|
||
DashedUpwardDiagonal,
|
||
/// <summary>
|
||
/// Dashed vertical style.
|
||
/// </summary>
|
||
DashedVertical,
|
||
/// <summary>
|
||
/// Diagonal brick style.
|
||
/// </summary>
|
||
DiagonalBrick,
|
||
/// <summary>
|
||
/// Diagonal cross style.
|
||
/// </summary>
|
||
DiagonalCross,
|
||
/// <summary>
|
||
/// Divot style.
|
||
/// </summary>
|
||
Divot,
|
||
/// <summary>
|
||
/// Dotted diamond style.
|
||
/// </summary>
|
||
DottedDiamond,
|
||
/// <summary>
|
||
/// Dotted grid style.
|
||
/// </summary>
|
||
DottedGrid,
|
||
/// <summary>
|
||
/// Forward diagonal style.
|
||
/// </summary>
|
||
ForwardDiagonal,
|
||
/// <summary>
|
||
/// Horizontal style.
|
||
/// </summary>
|
||
Horizontal,
|
||
/// <summary>
|
||
/// Horizontal brick style.
|
||
/// </summary>
|
||
HorizontalBrick,
|
||
/// <summary>
|
||
/// Large checker board style.
|
||
/// </summary>
|
||
[SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "CheckerBoard")]
|
||
LargeCheckerBoard,
|
||
/// <summary>
|
||
/// Large confetti style.
|
||
/// </summary>
|
||
LargeConfetti,
|
||
/// <summary>
|
||
/// Large grid style.
|
||
/// </summary>
|
||
LargeGrid,
|
||
/// <summary>
|
||
/// Light downward diagonal style.
|
||
/// </summary>
|
||
LightDownwardDiagonal,
|
||
/// <summary>
|
||
/// Light horizontal style.
|
||
/// </summary>
|
||
LightHorizontal,
|
||
/// <summary>
|
||
/// Light upward diagonal style.
|
||
/// </summary>
|
||
LightUpwardDiagonal,
|
||
/// <summary>
|
||
/// Light vertical style.
|
||
/// </summary>
|
||
LightVertical,
|
||
/// <summary>
|
||
/// Narrow horizontal style.
|
||
/// </summary>
|
||
NarrowHorizontal,
|
||
/// <summary>
|
||
/// Narrow vertical style.
|
||
/// </summary>
|
||
NarrowVertical,
|
||
/// <summary>
|
||
/// Outlined diamond style.
|
||
/// </summary>
|
||
OutlinedDiamond,
|
||
/// <summary>
|
||
/// Percent05 style.
|
||
/// </summary>
|
||
Percent05,
|
||
/// <summary>
|
||
/// Percent10 style.
|
||
/// </summary>
|
||
Percent10,
|
||
/// <summary>
|
||
/// Percent20 style.
|
||
/// </summary>
|
||
Percent20,
|
||
/// <summary>
|
||
/// Percent25 style.
|
||
/// </summary>
|
||
Percent25,
|
||
/// <summary>
|
||
/// Percent30 style.
|
||
/// </summary>
|
||
Percent30,
|
||
/// <summary>
|
||
/// Percent40 style.
|
||
/// </summary>
|
||
Percent40,
|
||
/// <summary>
|
||
/// Percent50 style.
|
||
/// </summary>
|
||
Percent50,
|
||
/// <summary>
|
||
/// Percent60 style.
|
||
/// </summary>
|
||
Percent60,
|
||
/// <summary>
|
||
/// Percent70 style.
|
||
/// </summary>
|
||
Percent70,
|
||
/// <summary>
|
||
/// Percent75 style.
|
||
/// </summary>
|
||
Percent75,
|
||
/// <summary>
|
||
/// Percent80 style.
|
||
/// </summary>
|
||
Percent80,
|
||
/// <summary>
|
||
/// Percent90 style.
|
||
/// </summary>
|
||
Percent90,
|
||
/// <summary>
|
||
/// Plaid style.
|
||
/// </summary>
|
||
Plaid,
|
||
/// <summary>
|
||
/// Shingle style.
|
||
/// </summary>
|
||
Shingle,
|
||
/// <summary>
|
||
/// Small checker board style.
|
||
/// </summary>
|
||
[SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "CheckerBoard")]
|
||
SmallCheckerBoard,
|
||
/// <summary>
|
||
/// Small confetti style.
|
||
/// </summary>
|
||
SmallConfetti,
|
||
/// <summary>
|
||
/// Small grid style.
|
||
/// </summary>
|
||
SmallGrid,
|
||
/// <summary>
|
||
/// Solid diamond style.
|
||
/// </summary>
|
||
SolidDiamond,
|
||
/// <summary>
|
||
/// Sphere style.
|
||
/// </summary>
|
||
Sphere,
|
||
/// <summary>
|
||
/// Trellis style.
|
||
/// </summary>
|
||
Trellis,
|
||
/// <summary>
|
||
/// Vertical style.
|
||
/// </summary>
|
||
Vertical,
|
||
/// <summary>
|
||
/// Wave style.
|
||
/// </summary>
|
||
Wave,
|
||
/// <summary>
|
||
/// Weave style.
|
||
/// </summary>
|
||
Weave,
|
||
/// <summary>
|
||
/// Wide downward diagonal style.
|
||
/// </summary>
|
||
WideDownwardDiagonal,
|
||
/// <summary>
|
||
/// Wide upward diagonal style.
|
||
/// </summary>
|
||
WideUpwardDiagonal,
|
||
/// <summary>
|
||
/// ZigZag style.
|
||
/// </summary>
|
||
[SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "ZigZag")]
|
||
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Zig")]
|
||
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Zag")]
|
||
ZigZag
|
||
};
|
||
|
||
/// <summary>
|
||
/// An enumeration that specifies the level of anti-aliasing quality.
|
||
/// </summary>
|
||
public enum TextAntiAliasingQuality
|
||
{
|
||
/// <summary>
|
||
/// Normal anti-aliasing quality.
|
||
/// </summary>
|
||
Normal,
|
||
/// <summary>
|
||
/// High anti-aliasing quality.
|
||
/// </summary>
|
||
High,
|
||
/// <summary>
|
||
/// System default anti-aliasing quality.
|
||
/// </summary>
|
||
SystemDefault
|
||
}
|
||
|
||
/// <summary>
|
||
/// An enumeration of anti-aliasing flags.
|
||
/// </summary>
|
||
[Flags]
|
||
public enum AntiAliasingStyles
|
||
{
|
||
/// <summary>
|
||
/// No anti-aliasing.
|
||
/// </summary>
|
||
None = 0,
|
||
|
||
/// <summary>
|
||
/// Use anti-aliasing when drawing text.
|
||
/// </summary>
|
||
Text = 1,
|
||
|
||
/// <summary>
|
||
/// Use anti-aliasing when drawing grahics primitives (e.g. lines, rectangle)
|
||
/// </summary>
|
||
Graphics = 2,
|
||
|
||
/// <summary>
|
||
/// Use anti-alias for everything.
|
||
/// </summary>
|
||
All = Text | Graphics
|
||
|
||
};
|
||
|
||
/// <summary>
|
||
/// An enumeration of marker styles.
|
||
/// </summary>
|
||
public enum MarkerStyle
|
||
{
|
||
/// <summary>
|
||
/// No marker is displayed for the series/data point.
|
||
/// </summary>
|
||
None = 0,
|
||
|
||
/// <summary>
|
||
/// A square marker is displayed.
|
||
/// </summary>
|
||
Square = 1,
|
||
|
||
/// <summary>
|
||
/// A circle marker is displayed.
|
||
/// </summary>
|
||
Circle = 2,
|
||
|
||
/// <summary>
|
||
/// A diamond-shaped marker is displayed.
|
||
/// </summary>
|
||
Diamond = 3,
|
||
|
||
/// <summary>
|
||
/// A triangular marker is displayed.
|
||
/// </summary>
|
||
Triangle = 4,
|
||
|
||
/// <summary>
|
||
/// A cross-shaped marker is displayed.
|
||
/// </summary>
|
||
Cross = 5,
|
||
|
||
/// <summary>
|
||
/// A 4-point star-shaped marker is displayed.
|
||
/// </summary>
|
||
Star4 = 6,
|
||
|
||
/// <summary>
|
||
/// A 5-point star-shaped marker is displayed.
|
||
/// </summary>
|
||
Star5 = 7,
|
||
|
||
/// <summary>
|
||
/// A 6-point star-shaped marker is displayed.
|
||
/// </summary>
|
||
Star6 = 8,
|
||
|
||
/// <summary>
|
||
/// A 10-point star-shaped marker is displayed.
|
||
/// </summary>
|
||
Star10 = 9
|
||
|
||
};
|
||
|
||
/// <summary>
|
||
/// An enumeration of gradient styles.
|
||
/// </summary>
|
||
public enum GradientStyle
|
||
{
|
||
/// <summary>
|
||
/// No gradient is used.
|
||
/// </summary>
|
||
None,
|
||
|
||
/// <summary>
|
||
/// Gradient is applied from left to right.
|
||
/// </summary>
|
||
LeftRight,
|
||
|
||
/// <summary>
|
||
/// Gradient is applied from top to bottom.
|
||
/// </summary>
|
||
TopBottom,
|
||
|
||
/// <summary>
|
||
/// Gradient is applied from the center outwards.
|
||
/// </summary>
|
||
Center,
|
||
|
||
/// <summary>
|
||
/// Gradient is applied diagonally from left to right.
|
||
/// </summary>
|
||
DiagonalLeft,
|
||
|
||
/// <summary>
|
||
/// Gradient is applied diagonally from right to left.
|
||
/// </summary>
|
||
DiagonalRight,
|
||
|
||
/// <summary>
|
||
/// Gradient is applied horizontally from the center outwards.
|
||
/// </summary>
|
||
HorizontalCenter,
|
||
|
||
/// <summary>
|
||
/// Gradient is applied vertically from the center outwards.
|
||
/// </summary>
|
||
VerticalCenter
|
||
};
|
||
|
||
#endregion
|
||
|
||
#region ChartElement
|
||
|
||
/// <summary>
|
||
/// Common chart helper methods used across different chart elements.
|
||
/// </summary>
|
||
internal class ChartHelper
|
||
{
|
||
#region Fields
|
||
|
||
/// <summary>
|
||
/// Maximum number of grid lines per Axis
|
||
/// </summary>
|
||
internal const int MaxNumOfGridlines = 10000;
|
||
|
||
#endregion // Fields
|
||
|
||
#region Constructor
|
||
|
||
/// <summary>
|
||
/// Private constructor to avoid instantiating the class
|
||
/// </summary>
|
||
private ChartHelper() { }
|
||
|
||
#endregion // Constructor
|
||
|
||
#region Methods
|
||
|
||
/// <summary>
|
||
/// Adjust the beginnin of the first interval depending on the type and size.
|
||
/// </summary>
|
||
/// <param name="start">Original start point.</param>
|
||
/// <param name="intervalSize">Interval size.</param>
|
||
/// <param name="type">AxisName of the interval (Month, Year, ...).</param>
|
||
/// <returns>Adjusted interval start position as double.</returns>
|
||
internal static double AlignIntervalStart(double start, double intervalSize, DateTimeIntervalType type)
|
||
{
|
||
return AlignIntervalStart(start, intervalSize, type, null);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Adjust the beginnin of the first interval depending on the type and size.
|
||
/// </summary>
|
||
/// <param name="start">Original start point.</param>
|
||
/// <param name="intervalSize">Interval size.</param>
|
||
/// <param name="type">AxisName of the interval (Month, Year, ...).</param>
|
||
/// <param name="series">First series connected to the axis.</param>
|
||
/// <returns>Adjusted interval start position as double.</returns>
|
||
internal static double AlignIntervalStart(double start, double intervalSize, DateTimeIntervalType type, Series series)
|
||
{
|
||
return AlignIntervalStart( start, intervalSize, type, series, true );
|
||
}
|
||
|
||
/// <summary>
|
||
/// Adjust the beginnin of the first interval depending on the type and size.
|
||
/// </summary>
|
||
/// <param name="start">Original start point.</param>
|
||
/// <param name="intervalSize">Interval size.</param>
|
||
/// <param name="type">AxisName of the interval (Month, Year, ...).</param>
|
||
/// <param name="series">First series connected to the axis.</param>
|
||
/// <param name="majorInterval">Interval is used for major gridlines or tickmarks.</param>
|
||
/// <returns>Adjusted interval start position as double.</returns>
|
||
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();
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Gets interval size as double number.
|
||
/// </summary>
|
||
/// <param name="current">Current value.</param>
|
||
/// <param name="interval">Interval size.</param>
|
||
/// <param name="type">AxisName of the interval (Month, Year, ...).</param>
|
||
/// <returns>Interval size as double.</returns>
|
||
internal static double GetIntervalSize(double current, double interval, DateTimeIntervalType type)
|
||
{
|
||
return GetIntervalSize(
|
||
current,
|
||
interval,
|
||
type,
|
||
null,
|
||
0,
|
||
DateTimeIntervalType.Number,
|
||
true,
|
||
true);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets interval size as double number.
|
||
/// </summary>
|
||
/// <param name="current">Current value.</param>
|
||
/// <param name="interval">Interval size.</param>
|
||
/// <param name="type">AxisName of the interval (Month, Year, ...).</param>
|
||
/// <param name="series">First series connected to the axis.</param>
|
||
/// <param name="intervalOffset">Offset size.</param>
|
||
/// <param name="intervalOffsetType">Offset type(Month, Year, ...).</param>
|
||
/// <param name="forceIntIndex">Force Integer indexed</param>
|
||
/// <returns>Interval size as double.</returns>
|
||
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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets interval size as double number.
|
||
/// </summary>
|
||
/// <param name="current">Current value.</param>
|
||
/// <param name="interval">Interval size.</param>
|
||
/// <param name="type">AxisName of the interval (Month, Year, ...).</param>
|
||
/// <param name="series">First series connected to the axis.</param>
|
||
/// <param name="intervalOffset">Offset size.</param>
|
||
/// <param name="intervalOffsetType">Offset type(Month, Year, ...).</param>
|
||
/// <param name="forceIntIndex">Force Integer indexed</param>
|
||
/// <param name="forceAbsInterval">Force Integer indexed</param>
|
||
/// <returns>Interval size as double.</returns>
|
||
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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Check if series is indexed. IsXValueIndexed flag is set or all X values are zeros.
|
||
/// </summary>
|
||
/// <param name="series">Data series to test.</param>
|
||
/// <returns>True if series is indexed.</returns>
|
||
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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Check if all data points in the series have X value set to 0.
|
||
/// </summary>
|
||
/// <param name="series">Data series to check.</param>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Check if any series is indexed. IsXValueIndexed flag is set or all X values are zeros.
|
||
/// </summary>
|
||
/// <param name="common">Reference to common chart classes.</param>
|
||
/// <param name="series">Data series names.</param>
|
||
/// <returns>True if any series is indexed.</returns>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Check if all data points in many series have X value set to 0.
|
||
/// </summary>
|
||
/// <param name="common">Reference to common chart classes.</param>
|
||
/// <param name="series">Data series.</param>
|
||
/// <returns>True if all data points have value 0.</returns>
|
||
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
|
||
}
|