//-------------------------------------------------------------
//
// Copyright © Microsoft Corporation. All Rights Reserved.
//
//-------------------------------------------------------------
// @owner=alexgor, deliant
//=================================================================
// File: DataSries.cs
//
// Namespace: System.Web.UI.WebControls[Windows.Forms].Charting.Data
//
// Classes: SeriesCollection, Series
//
// Purpose: Chart series collection class and series properties class.
//
// Reviewed: AG - Aug 1, 2002;
// GS - Aug 7, 2002
//
//===================================================================
#region Used namespaces
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections.Generic;
using System.Collections;
using System.Data;
using System.Drawing;
using System.Drawing.Design;
using System.Globalization;
using System.Diagnostics.CodeAnalysis;
#if Microsoft_CONTROL
using System.Windows.Forms.DataVisualization.Charting.Data;
using System.Windows.Forms.DataVisualization.Charting.ChartTypes;
using System.Windows.Forms.DataVisualization.Charting.Utilities;
using System.Windows.Forms.DataVisualization.Charting.Borders3D;
using System.Windows.Forms.DataVisualization.Charting;
using System.ComponentModel.Design.Serialization;
using System.Reflection;
#else
using System.Web;
using System.Web.UI;
using System.Web.UI.DataVisualization.Charting;
using System.Web.UI.DataVisualization.Charting.ChartTypes;
using System.Web.UI.DataVisualization.Charting.Utilities;
using System.Web.UI.DataVisualization.Charting.Data;
#endif
#endregion
#if Microsoft_CONTROL
namespace System.Windows.Forms.DataVisualization.Charting
#else
namespace System.Web.UI.DataVisualization.Charting
#endif
{
#region Series enumerations
///
/// Chart axis type (Primary or Secondary).
///
public enum AxisType
{
///
/// Primary axis. For X axis - bottom, for Y axis - left.
///
Primary,
///
/// Secondary axis. For X axis - top, for Y axis - right.
///
Secondary
};
///
/// Sorting order (Ascending or Descending).
///
public enum PointSortOrder
{
///
/// Ascending sorting order
///
Ascending,
///
/// Descending sorting order
///
Descending
}
#endregion
///
/// Data series collection
///
[
SRDescription("DescriptionAttributeSeriesCollection_SeriesCollection"),
]
#if ASPPERM_35
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
#endif
public class SeriesCollection : ChartNamedElementCollection
{
#region Constructors
///
/// Data series collection object constructor.
///
internal SeriesCollection(DataManager dataManager)
: base(dataManager)
{
}
#endregion
#region Methods
///
/// Creates a new Series with the specified name and adds it to the collection.
///
/// The new chart area name.
/// New series
public Series Add(string name)
{
Series series = new Series(name);
this.Add(series);
return series;
}
///
/// Fixes the name references of the item.
///
/// Item to verify and fix.
internal override void FixNameReferences(Series item)
{
if (item != null && Chart != null)
{
if (String.IsNullOrEmpty(item.ChartArea) && Chart.ChartAreas != null)
{
item.ChartArea = Chart.ChartAreas.DefaultNameReference;
}
if (String.IsNullOrEmpty(item.Legend) && Chart.Legends != null)
{
item.Legend = Chart.Legends.DefaultNameReference;
}
}
}
#endregion
#region Event handlers
///
/// Updates the Series' references to ChartAreas.
///
/// The sender.
/// The instance containing the event data.
internal void ChartAreaNameReferenceChanged(object sender, NameReferenceChangedEventArgs e)
{
foreach (Series series in this)
if (series.ChartArea == e.OldName)
series.ChartArea = e.NewName;
}
///
/// Updates the Series' references to Legends.
///
/// The sender.
/// The instance containing the event data.
internal void LegendNameReferenceChanged(object sender, NameReferenceChangedEventArgs e)
{
foreach (Series series in this)
if (series.Legend == e.OldName)
series.Legend = e.NewName;
}
#endregion
}
///
/// The class stores the data points and the default series properties.
///
[
SRDescription("DescriptionAttributeSeries_Series"),
DefaultProperty("Points"),
]
#if ASPPERM_35
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
#endif
public class Series : DataPointCustomProperties
{
#region Fields
// Private data members, which store properties values
private ChartValueType _xValueType = ChartValueType.Auto;
private ChartValueType _yValueType = ChartValueType.Auto;
private bool _isXValueIndexed = false;
private int _yValuesPerPoint = 1;
private int _markersStep = 1;
private ChartColorPalette _colorPalette = ChartColorPalette.None;
private AxisType _xAxisType = AxisType.Primary;
private AxisType _yAxisType = AxisType.Primary;
#if SUBAXES
private string _ySubAxisName = string.Empty;
private string _xSubAxisName = string.Empty;
#endif // SUBAXES
private DataPointCustomProperties _emptyPointCustomProperties = null;
private DataPointCollection _points;
private int _shadowOffset = 0;
private Color _shadowColor = Color.FromArgb(128, 0, 0, 0);
private string _chartType = ChartTypeNames.Column;
private string _chartArea = String.Empty;
// Series enabled flag
private bool _enabled = true;
// Legend name used by this series
private string _legend = String.Empty;
// Member of the chart data source used to data bind to the X value of the series.
private string _dataSourceXMember = String.Empty;
// Members of the chart data source used to data bind to the Y values of the series.
private string _dataSourceYMembers = String.Empty;
// Automatic values type flags
internal bool autoXValueType = false;
internal bool autoYValueType = false;
// Total Y value of all data points
private double _totalYvalue = double.NaN;
// Array of dummy data used at design time
private double[] _dummyDoubleValues = null;
// X value type if X value is indexed
internal ChartValueType indexedXValueType = ChartValueType.Auto;
// Default properties
static internal DataPointCustomProperties defaultCustomProperties = InitializeDefaultCustomProperties();
// Indicates that a temp. marker style was set for drawing
internal bool tempMarkerStyleIsSet = false;
// Indicates that number of Y values should be checked
private bool _checkPointsNumber = true;
// SmartLabelStyle style
private SmartLabelStyle _smartLabelStyle = null;
// Indicates that there is no custom axis labels in data points or series
internal bool noLabelsInPoints = true;
// Indicates if series has all X values set to 0
internal bool xValuesZeros = false;
// Indicates if check for series X zero values was done
internal bool xValuesZerosChecked = false;
// fake data points for selector service in design time.
// note: in design time fake points are generated
// with short life time - during painting.
// this collection keep a copy of design time datapoints.
internal DataPointCollection fakeDataPoints;
#endregion
#region Series properties fields
///
/// Data point label text.
///
internal string label = "";
///
/// Data point X axis label text.
///
internal string axisLabel = "";
///
/// Data point label format string
///
internal string labelFormat = "";
///
/// If true shows point's value as a label.
///
internal bool showLabelAsValue = false;
///
/// Data point color
///
internal Color color = Color.Empty;
///
/// Data point border color
///
internal Color borderColor = Color.Empty;
///
/// Data point border style
///
internal ChartDashStyle borderDashStyle = ChartDashStyle.Solid;
///
/// Data point border width
///
internal int borderWidth = 1;
///
/// Data point marker border width
///
internal int markerBorderWidth = 1;
///
/// Data point background image
///
internal string backImage = "";
///
/// Data point background image drawing mode.
///
internal ChartImageWrapMode backImageWrapMode = ChartImageWrapMode.Tile;
///
/// Background image transparent color.
///
internal Color backImageTransparentColor = Color.Empty;
///
/// Background image alignment used by ClampUnscale drawing mode.
///
internal ChartImageAlignmentStyle backImageAlignment = ChartImageAlignmentStyle.TopLeft;
///
/// Data point background gradient type.
///
internal GradientStyle backGradientStyle = GradientStyle.None;
///
/// Data point background gradient end color
///
internal Color backSecondaryColor = Color.Empty;
///
/// Data point hatch style
///
internal ChartHatchStyle backHatchStyle = ChartHatchStyle.None;
///
/// Font cache for the fonts used in the Series and DataPoint
///
private FontCache _fontCache = new FontCache();
///
/// Data point font
///
internal Font font = null;
///
/// Data point line color
///
internal Color fontColor = Color.Black;
///
/// Data point font angle
///
internal int fontAngle = 0;
///
/// Data point marker style
///
internal MarkerStyle markerStyle = MarkerStyle.None;
///
/// Data point marker size
///
internal int markerSize = 5;
///
/// Data point marker image
///
internal string markerImage = "";
///
/// Data point marker image transparent color.
///
internal Color markerImageTransparentColor = Color.Empty;
///
/// Data point marker color
///
internal Color markerColor = Color.Empty;
///
/// Data point marker border color
///
internal Color markerBorderColor = Color.Empty;
///
/// The tooltip.
///
internal string toolTip = "";
#if !Microsoft_CONTROL
///
/// URL target of the area.
///
internal string url = "";
///
/// Other attributes of the area.
///
internal string mapAreaAttributes = "";
///
/// Other attributes of the area.
///
internal string postbackValue = "";
#endif
///
/// Indicates that item is shown in the legend.
///
internal bool showInLegend = true;
///
/// Text of the item in the legend
///
internal string legendText = "";
///
/// Tooltip of the item in the legend
///
internal string legendToolTip = "";
///
/// Data point label back color
///
internal Color labelBackColor = Color.Empty;
///
/// Data point label border color
///
internal Color labelBorderColor = Color.Empty;
///
/// Data point label border style
///
internal ChartDashStyle labelBorderDashStyle = ChartDashStyle.Solid;
///
/// Data point label border width
///
internal int labelBorderWidth = 1;
///
/// Tooltip of the data point label
///
internal string labelToolTip = "";
#if !Microsoft_CONTROL
///
/// URL target of the data point label.
///
internal string labelUrl = "";
///
/// Other attributes of the data point label.
///
internal string labelMapAreaAttributes = "";
///
/// Other attributes of the area.
///
internal string labelPostbackValue = "";
///
/// URL target of the item in the legend.
///
internal string legendUrl = "";
///
/// Other attributes of the legend map area.
///
internal string legendMapAreaAttributes = "";
///
/// Other attributes of the area.
///
internal string legendPostbackValue = "";
#endif
#endregion
#region Constructors and initialization
///
/// Initializes the default custom properties field.
///
/// A DataPointCustomProperties initialized to defaults
private static DataPointCustomProperties InitializeDefaultCustomProperties()
{
DataPointCustomProperties customProperties = new DataPointCustomProperties(null, false);
customProperties.SetDefault(true);
customProperties.pointCustomProperties = true;
return customProperties;
}
///
/// Series object constructor.
///
public Series() : base(null, false)
{
InitProperties(null, 0);
}
///
/// Series object constructor.
///
/// Name of the data series
public Series(string name) : base(null, false)
{
if(name == null)
{
throw (new ArgumentNullException(SR.ExceptionDataSeriesNameIsEmpty));
}
InitProperties(name, 0);
}
///
/// Series object constructor.
///
/// Name of the data series.
/// Number of y values per data point.
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
Justification = "Y is a cartesian coordinate and well understood")]
public Series(string name, int yValues)
: base(null, false)
{
if(name == null)
{
throw (new ArgumentNullException("name", SR.ExceptionDataSeriesNameIsEmpty));
}
if(YValuesPerPoint < 1)
{
throw (new ArgumentOutOfRangeException("yValues", SR.ExceptionDataSeriesYValuesPerPointIsZero));
}
InitProperties(name, yValues);
}
///
/// Initialize series properties
///
private void InitProperties(string name, int YValuesPerPoint)
{
this.font = _fontCache.DefaultFont;
this.series = this;
this._emptyPointCustomProperties = new DataPointCustomProperties(this, false);
this._emptyPointCustomProperties.series = this;
// Initialize properties
_points = new DataPointCollection(this);
fakeDataPoints = new DataPointCollection(this);
if(name != null)
{
base.Name = name;
}
if(YValuesPerPoint != 0)
{
_yValuesPerPoint = YValuesPerPoint;
}
base.SetDefault(true);
_emptyPointCustomProperties.SetDefault(true);
_emptyPointCustomProperties.pointCustomProperties = true;
//
#if !SQLRS_CONTROL
// Use transparent colors for empty points
emptyPointAttributes.Color = Color.Transparent;
emptyPointAttributes.BorderColor = Color.Transparent;
emptyPointAttributes.FontColor = Color.Transparent;
emptyPointAttributes.MarkerColor = Color.Transparent;
emptyPointAttributes.MarkerBorderColor = Color.Transparent;
#endif //!SQLRS_CONTROL
// Create SmartLabelStyle style object
_smartLabelStyle = new SmartLabelStyle(this);
}
#endregion
#region Helper methods
///
/// Gets series caption that may not be the same as series name.
///
/// Series caption string.
internal string GetCaption()
{
if (this.IsCustomPropertySet("SeriesCaption"))
{
return this["SeriesCaption"];
}
return this.Name;
}
///
/// Gets custom points depth and gap depth from series properties.
///
/// Chart graphics.
/// Cate----cal axis.
/// Returns point depth.
/// Return point gap depth.
internal void GetPointDepthAndGap(
ChartGraphics graph,
Axis axis,
ref double pointDepth,
ref double pointGapDepth)
{
// Check if series provide custom value for point depth in pixels
string attribValue = this[CustomPropertyName.PixelPointDepth];
if(attribValue != null)
{
try
{
pointDepth = CommonElements.ParseDouble(attribValue);
}
catch
{
throw (new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid2("PixelPointDepth")));
}
if (pointDepth <= 0)
{
throw (new InvalidOperationException(SR.ExceptionCustomAttributeIsNotLargerThenZiro("PixelPointDepth")));
}
if (pointDepth > CustomPropertyRegistry.MaxValueOfPixelAttribute)
{
throw (new InvalidOperationException(SR.ExceptionCustomAttributeMustBeInRange("PixelPointDepth", (0).ToString(CultureInfo.CurrentCulture), CustomPropertyRegistry.MaxValueOfPixelAttribute.ToString(CultureInfo.CurrentCulture))));
}
SizeF relativeSize = graph.GetRelativeSize(new SizeF((float)pointDepth, (float)pointDepth));
pointDepth = relativeSize.Width;
if(axis.AxisPosition == AxisPosition.Left || axis.AxisPosition == AxisPosition.Right)
{
pointDepth = relativeSize.Height;
}
}
// Check if series provide custom value for point gap depth in pixels
attribValue = this[CustomPropertyName.PixelPointGapDepth];
if(attribValue != null)
{
try
{
pointGapDepth = CommonElements.ParseDouble(attribValue);
}
catch
{
throw (new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid2("PixelPointGapDepth")));
}
if (pointGapDepth <= 0)
{
throw (new InvalidOperationException(SR.ExceptionCustomAttributeIsNotLargerThenZiro("PixelPointGapDepth")));
}
if (pointGapDepth > CustomPropertyRegistry.MaxValueOfPixelAttribute)
{
throw (new InvalidOperationException(SR.ExceptionCustomAttributeMustBeInRange("PixelPointGapDepth", (0).ToString(CultureInfo.CurrentCulture), CustomPropertyRegistry.MaxValueOfPixelAttribute.ToString(CultureInfo.CurrentCulture))));
}
SizeF relativeSize = graph.GetRelativeSize(new SizeF((float)pointGapDepth, (float)pointGapDepth));
pointGapDepth = relativeSize.Width;
if(axis.AxisPosition == AxisPosition.Left || axis.AxisPosition == AxisPosition.Right)
{
pointGapDepth = relativeSize.Height;
}
}
}
///
/// Gets data point width in relative coordinates.
///
/// Chart graphics.
/// Axis object.
/// Current minimum axis interval.
/// Default width in percentage of interval.
/// Point width.
internal double GetPointWidth(
ChartGraphics graph,
Axis axis,
double interval,
double defaultWidth)
{
double pointPercentageWidth = defaultWidth;
double pointWidth = 0.0;
// Check if series provide custom value for point width in percentage of interval
string strWidth = this[CustomPropertyName.PointWidth];
if(strWidth != null)
{
pointPercentageWidth = CommonElements.ParseDouble(strWidth);
}
// Get column width in relative and pixel coordinates
pointWidth = axis.GetPixelInterval( interval * pointPercentageWidth );
SizeF pointSize = graph.GetAbsoluteSize(new SizeF((float)pointWidth, (float)pointWidth));
double pixelPointWidth = pointSize.Width;
if(axis.AxisPosition == AxisPosition.Left || axis.AxisPosition == AxisPosition.Right)
{
pixelPointWidth = pointSize.Height;
}
// Check if series provide custom value for Min point width in pixels
bool usePixelWidth = false;
string attribValue = this[CustomPropertyName.MinPixelPointWidth];
if(attribValue != null)
{
double minPixelPointWidth = 0.0;
try
{
minPixelPointWidth = CommonElements.ParseDouble(attribValue);
}
catch
{
throw(new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid2("MinPixelPointWidth")));
}
if(minPixelPointWidth <= 0.0)
{
throw(new InvalidOperationException(SR.ExceptionCustomAttributeIsNotLargerThenZiro("MinPixelPointWidth")));
}
if (minPixelPointWidth > CustomPropertyRegistry.MaxValueOfPixelAttribute)
{
throw (new InvalidOperationException(SR.ExceptionCustomAttributeMustBeInRange("MinPixelPointWidth", (0).ToString(CultureInfo.CurrentCulture), CustomPropertyRegistry.MaxValueOfPixelAttribute.ToString(CultureInfo.CurrentCulture))));
}
if(pixelPointWidth < minPixelPointWidth)
{
usePixelWidth = true;
pixelPointWidth = minPixelPointWidth;
}
}
// Check if series provide custom value for Max point width in pixels
attribValue = this[CustomPropertyName.MaxPixelPointWidth];
if(attribValue != null)
{
double maxPixelPointWidth = 0.0;
try
{
maxPixelPointWidth = CommonElements.ParseDouble(attribValue);
}
catch
{
throw(new InvalidOperationException( SR.ExceptionCustomAttributeValueInvalid2("MaxPixelPointWidth")));
}
if(maxPixelPointWidth <= 0)
{
throw(new InvalidOperationException(SR.ExceptionCustomAttributeIsNotLargerThenZiro("MaxPixelPointWidth")));
}
if(pixelPointWidth > maxPixelPointWidth)
{
usePixelWidth = true;
pixelPointWidth = maxPixelPointWidth;
}
}
// Check if series provide custom value for point width in pixels
attribValue = this[CustomPropertyName.PixelPointWidth];
if(attribValue != null)
{
usePixelWidth = true;
pixelPointWidth = 0.0;
try
{
pixelPointWidth = CommonElements.ParseDouble(attribValue);
}
catch
{
throw(new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid2("PixelPointWidth")));
}
if(pixelPointWidth <= 0)
{
throw(new InvalidOperationException(SR.ExceptionCustomAttributeIsNotLargerThenZiro("PixelPointWidth")));
}
if (pixelPointWidth > CustomPropertyRegistry.MaxValueOfPixelAttribute)
{
throw (new InvalidOperationException(SR.ExceptionCustomAttributeMustBeInRange("PixelPointWidth", (0).ToString(CultureInfo.CurrentCulture), CustomPropertyRegistry.MaxValueOfPixelAttribute.ToString(CultureInfo.CurrentCulture))));
}
}
// Translate pixel width to relative coordinates
if(usePixelWidth)
{
SizeF pointRelativeSize = graph.GetRelativeSize(new SizeF((float)pixelPointWidth, (float)pixelPointWidth));
pointWidth = pointRelativeSize.Width;
if(axis.AxisPosition == AxisPosition.Left || axis.AxisPosition == AxisPosition.Right)
{
pointWidth = pointRelativeSize.Height;
}
}
return pointWidth;
}
///
/// Get chart type name by it's type
///
/// Chart type.
/// Chart type name.
static internal string GetChartTypeName(SeriesChartType type)
{
if(type == SeriesChartType.StackedArea100)
return ChartTypeNames.OneHundredPercentStackedArea;
if(type == SeriesChartType.StackedBar100)
return ChartTypeNames.OneHundredPercentStackedBar;
if(type == SeriesChartType.StackedColumn100)
return ChartTypeNames.OneHundredPercentStackedColumn;
return Enum.GetName(typeof(SeriesChartType), type);
}
///
/// Checks if Y values of the series represent date-time.
///
/// True if date-time.
internal bool IsYValueDateTime()
{
if(this.YValueType == ChartValueType.Date ||
this.YValueType == ChartValueType.DateTime ||
this.YValueType == ChartValueType.Time ||
this.YValueType == ChartValueType.DateTimeOffset)
{
return true;
}
return false;
}
///
/// Checks if X values of the series represent date-time.
///
/// True if date-time.
internal bool IsXValueDateTime()
{
if(this.XValueType == ChartValueType.Date ||
this.XValueType == ChartValueType.DateTime ||
this.XValueType == ChartValueType.Time ||
this.XValueType == ChartValueType.DateTimeOffset)
{
return true;
}
return false;
}
///
/// Checks if series is visible.
///
/// True if series is visible.
internal bool IsVisible()
{
// Check if enabled flag is set and the ChartArea is defined
if(this.Enabled && !String.IsNullOrEmpty(this.ChartArea))
{
return true;
}
return false;
}
///
/// Checks if series chart type uses a "Fast" mode chart type.
///
/// True if series uses "Fast" mode chart type.
internal bool IsFastChartType()
{
// Check if fast mode chart type is used in the series
if(this.ChartType == SeriesChartType.FastLine)
{
return true;
}
// Check if fast mode chart type is used in the series
if(this.ChartType == SeriesChartType.FastPoint)
{
return true;
}
return false;
}
///
/// Throws exception if specified value type is not supported.
///
/// Value type to check.
internal void CheckSupportedTypes(Type type)
{
// Check parameters type
if(type == typeof(Double) ||
type == typeof(DateTime) ||
type == typeof(String) ||
type == typeof(Int32) ||
type == typeof(UInt32) ||
type == typeof(Decimal) ||
type == typeof(Single) ||
type == typeof(Int16) ||
type == typeof(UInt16) ||
type == typeof(Int64) ||
type == typeof(UInt64) ||
type == typeof(Byte) ||
type == typeof(SByte) ||
type == typeof(System.DBNull) ||
type == typeof(Boolean) )
{
return;
}
// Unsupported parameter type
throw(new ArgumentException(SR.ExceptionDataSeriesPointTypeUnsupported( type.ToString() ) ));
}
///
/// Apply palette colors to the data series points if UsePaletteColors property is set.
///
internal void ApplyPaletteColors()
{
// Use Series or Data Manager palette
DataManager dataManager = this.Common.DataManager;
ChartColorPalette currentPalette = (this.Palette == ChartColorPalette.None) ?
dataManager.Palette : this.Palette;
// if it is still none - check if custom colors pallete is empty.
if (
currentPalette == ChartColorPalette.None &&
dataManager.PaletteCustomColors.Length == 0
)
{
currentPalette = ChartColorPalette.BrightPastel;
}
// Get palette colors
int colorIndex = 0;
Color[] paletteColors = (currentPalette == ChartColorPalette.None) ?
dataManager.PaletteCustomColors : ChartPaletteColors.GetPaletteColors(currentPalette);
foreach(DataPoint dataPoint in _points)
{
// Change color of the series data points only if no color is set
if((!dataPoint.IsCustomPropertySet(CommonCustomProperties.Color) || dataPoint.tempColorIsSet ) && !dataPoint.IsEmpty)
{
dataPoint.SetAttributeObject(CommonCustomProperties.Color, paletteColors[colorIndex]);
dataPoint.tempColorIsSet = true;
++colorIndex;
if(colorIndex >= paletteColors.Length)
{
colorIndex = 0;
}
}
}
}
///
/// Gets design time dummy data.
///
/// AxisName of the data to get.
/// Dummy data for chart in design-time.
internal IEnumerable GetDummyData(ChartValueType type)
{
string[] stringValues = { "abc1", "abc2", "abc3", "abc4", "abc5", "abc6" };
DateTime[] dateValues = { DateTime.Now.Date, DateTime.Now.Date.AddDays(1), DateTime.Now.Date.AddDays(2), DateTime.Now.Date.AddDays(3), DateTime.Now.Date.AddDays(4), DateTime.Now.Date.AddDays(4) };
// Fill array of random data
if(_dummyDoubleValues == null)
{
#if !SQLRS_CONTROL
Random random2 = new Random(unchecked((int)DateTime.Now.Ticks +
this.Color.B + this.Color.G + this.Color.R));
#else
int seed = 0;
for (int index = 0; index < this.Name.Length; index++)
seed += (int)this.Name[index];
Random random2 = new Random(seed);
#endif
_dummyDoubleValues = new double[6];
for(int valueIndex = 0; valueIndex < 6; valueIndex++)
{
_dummyDoubleValues[valueIndex] = random2.Next(10, 100);
}
}
// Return dummy data
if(type == ChartValueType.DateTime || type == ChartValueType.Date || type == ChartValueType.DateTimeOffset)
{
return dateValues;
}
else if(type == ChartValueType.Time)
{
dateValues = new DateTime[] { DateTime.Now, DateTime.Now.AddMinutes(1), DateTime.Now.AddMinutes(2), DateTime.Now.AddMinutes(3), DateTime.Now.AddMinutes(4), DateTime.Now.AddMinutes(4) };
return dateValues;
}
else if(type == ChartValueType.String)
{
return stringValues;
}
return _dummyDoubleValues;
}
///
/// Returns total of the Y values.
///
/// Y values total.
internal double GetTotalYValue()
{
return this.GetTotalYValue(0);
}
///
/// Returns total of the Y values.
///
/// Index of the Y value to use
/// Y values total.
internal double GetTotalYValue(int yValueIndex)
{
if(yValueIndex == 0)
{
// Total was already calculated
if(!double.IsNaN(_totalYvalue))
{
return _totalYvalue;
}
// Calculate total
_totalYvalue = 0;
foreach(DataPoint point in this.Points)
{
_totalYvalue += point.YValues[yValueIndex];
}
return _totalYvalue;
}
// Check if series has enough Y values
if(yValueIndex >= this.YValuesPerPoint)
{
throw(new InvalidOperationException( SR.ExceptionDataSeriesYValueIndexNotExists(yValueIndex.ToString(CultureInfo.InvariantCulture), this.Name ) ) );
}
// Calculate total
double yValue = 0;
foreach(DataPoint point in this.Points)
{
yValue += point.YValues[yValueIndex];
}
return yValue;
}
///
/// Replaces predefined keyword inside the string with their values.
///
/// Original string with keywords.
/// Modified string.
internal override string ReplaceKeywords(string strOriginal)
{
// Nothing to process
if(strOriginal == null || strOriginal.Length == 0)
return strOriginal;
// Replace all "\n" strings with '\n' character
string result = strOriginal.Replace("\\n", "\n");
// #SERIESNAME - series name
result = result.Replace(KeywordName.SeriesName, this.Name);
result = result.Replace(KeywordName.Ser, this.Name); // #SER Depricated Keyword
// #CUSTOMPROPERTY - one of the custom attributes by name
result = DataPoint.ReplaceCustomPropertyKeyword(result, this);
// #TOTAL - total of Y values
result = ReplaceOneKeyword(
this.Chart,
this,
this.Tag,
ChartElementType.Nothing,
result,
KeywordName.Total,
SeriesValuesFormulaType.Total,
this.YValueType,
"");
// #AVG - total of Y values
result = ReplaceOneKeyword(
this.Chart,
this,
this.Tag,
ChartElementType.Nothing,
result,
KeywordName.Avg,
SeriesValuesFormulaType.Average,
this.YValueType,
"");
// #MAX - total of Y values
result = ReplaceOneKeyword(
this.Chart,
this,
this.Tag,
ChartElementType.Nothing,
result,
KeywordName.Max,
SeriesValuesFormulaType.Maximum,
this.YValueType,
"");
// #MIN - total of Y values
result = ReplaceOneKeyword(
this.Chart,
this,
this.Tag,
ChartElementType.Nothing,
result,
KeywordName.Min,
SeriesValuesFormulaType.Minimum,
this.YValueType,
"");
// #FIRST - total of Y values
result = ReplaceOneKeyword(
this.Chart,
this,
this.Tag,
ChartElementType.Nothing,
result,
KeywordName.First,
SeriesValuesFormulaType.First,
this.YValueType,
"");
// #LAST - total of Y values
result = ReplaceOneKeyword(
this.Chart,
this,
this.Tag,
ChartElementType.Nothing,
result,
KeywordName.Last,
SeriesValuesFormulaType.Last,
this.YValueType,
"");
// #LEGENDTEXT - series name
result = result.Replace(KeywordName.LegendText, this.LegendText);
return result;
}
///
/// Helper function which replaces one keyword.
///
/// Chart object reference.
/// Chart element type.
/// Object being formatted.
/// Additional object tag.
/// Original string.
/// Keyword to replace.
/// Formula used to calculate the value.
/// AxisName of value.
/// Default format string.
/// Result string.
internal string ReplaceOneKeyword(
Chart chart,
object obj,
object objTag,
ChartElementType elementType,
string strOriginal,
string keyword,
SeriesValuesFormulaType formulaType,
ChartValueType valueType,
string defaultFormat)
{
string result = strOriginal;
int keyIndex = -1;
while((keyIndex = result.IndexOf(keyword, StringComparison.Ordinal)) != -1)
{
int keyEndIndex = keyIndex + keyword.Length;
// Get optional Y value index
int yValueIndex = 0;
if(result.Length > keyEndIndex + 1 &&
result[keyEndIndex] == 'Y' &&
char.IsDigit(result[keyEndIndex + 1]))
{
yValueIndex = int.Parse(result.Substring(keyEndIndex + 1, 1), CultureInfo.InvariantCulture);
keyEndIndex += 2;
}
// Get optional format
string format = defaultFormat;
if(result.Length > keyEndIndex && result[keyEndIndex] == '{')
{
int formatEnd = result.IndexOf('}', keyEndIndex);
if(formatEnd == -1)
{
throw(new InvalidOperationException( SR.ExceptionDataSeriesKeywordFormatInvalid( result )));
}
format = result.Substring(keyEndIndex, formatEnd - keyEndIndex).Trim('{', '}');
keyEndIndex = formatEnd + 1;
}
// Remove keyword string (with optional format)
result = result.Remove(keyIndex, keyEndIndex - keyIndex);
// Calculate value
double totalValue = this.GetTotalYValue(yValueIndex);
double keywordValue = 0.0;
switch(formulaType)
{
case(SeriesValuesFormulaType.Average):
{
if(this.Points.Count > 0)
{
keywordValue = totalValue / this.Points.Count;
}
break;
}
case(SeriesValuesFormulaType.First):
{
if(this.Points.Count > 0)
{
keywordValue = this.Points[0].YValues[yValueIndex];
}
break;
}
case(SeriesValuesFormulaType.Last):
{
if(this.Points.Count > 0)
{
keywordValue = this.Points[this.Points.Count - 1].YValues[yValueIndex];
}
break;
}
case(SeriesValuesFormulaType.Maximum):
{
if (this.Points.Count > 0)
{
keywordValue = double.MinValue;
foreach (DataPoint point in this.Points)
{
keywordValue = Math.Max(keywordValue, point.YValues[yValueIndex]);
}
}
break;
}
case(SeriesValuesFormulaType.Minimum):
{
if (this.Points.Count > 0)
{
keywordValue = double.MaxValue;
foreach (DataPoint point in this.Points)
{
keywordValue = Math.Min(keywordValue, point.YValues[yValueIndex]);
}
}
break;
}
case(SeriesValuesFormulaType.Total):
{
keywordValue = totalValue;
break;
}
}
// Insert value
result = result.Insert(keyIndex,
ValueConverter.FormatValue(chart, obj, objTag, keywordValue, format, valueType, elementType));
}
return result;
}
///
/// Helper function which replaces one keyword.
///
/// Chart object reference.
/// Chart element type.
/// Object being formatted.
/// Additional object tag.
/// Original string.
/// Keyword to replace.
/// Value to replace with.
/// AxisName of value.
/// Default format string.
/// Result string.
internal string ReplaceOneKeyword(Chart chart, object obj, object objTag, ChartElementType elementType, string strOriginal, string keyword, double value, ChartValueType valueType, string defaultFormat)
{
string result = strOriginal;
int keyIndex = -1;
while((keyIndex = result.IndexOf(keyword, StringComparison.Ordinal)) != -1)
{
// Get optional format
int keyEndIndex = keyIndex + keyword.Length;
string format = defaultFormat;
if(result.Length > keyEndIndex && result[keyEndIndex] == '{')
{
int formatEnd = result.IndexOf('}', keyEndIndex);
if(formatEnd == -1)
{
throw(new InvalidOperationException( SR.ExceptionDataSeriesKeywordFormatInvalid(result)));
}
format = result.Substring(keyEndIndex, formatEnd - keyEndIndex).Trim('{', '}');
keyEndIndex = formatEnd + 1;
}
// Remove keyword string (with optional format)
result = result.Remove(keyIndex, keyEndIndex - keyIndex);
// Insert value
result = result.Insert(keyIndex,
ValueConverter.FormatValue(chart, obj, objTag, value, format, valueType, elementType));
}
return result;
}
#endregion
#region Points sorting methods
///
/// Sorts the points in the series.
///
/// Sorting order.
/// Value used for sorting (X, Y, Y2, ...).
public void Sort(PointSortOrder pointSortOrder, string sortBy)
{
// Check arguments
if (sortBy==null)
throw new ArgumentNullException("sortBy");
// Sort items using data points comparer class
DataPointComparer comparer = new DataPointComparer(this, pointSortOrder, sortBy);
this.Points.ItemList.Sort(comparer);
// Invalidate chart area only
this.Invalidate(true, false);
}
///
/// Sorts the points in the series.
///
/// Sorting order.
public void Sort(PointSortOrder pointSortOrder)
{
Sort(pointSortOrder, "Y");
}
///
/// Sorts the points in the series using IComparer interface.
///
/// IComparer interface.
public void Sort(IComparer comparer)
{
// Check arguments
if (comparer == null)
throw new ArgumentNullException("comparer");
// Sort points
this.Points.ItemList.Sort(comparer);
// Invalidate chart area only
this.Invalidate(true, false);
}
#endregion
#region Series preparation/cleanup for drawing
///
/// Moves the position markers.
///
/// From series.
/// To series.
internal static void MovePositionMarkers(Series fromSeries, Series toSeries)
{
foreach (DataPoint dp in fromSeries.Points)
{
if (dp.IsCustomPropertySet("OriginalPointIndex"))
{
int index = -1;
if (Int32.TryParse(dp["OriginalPointIndex"], NumberStyles.Integer, CultureInfo.InvariantCulture, out index))
{
if (index > -1 && index < toSeries.Points.Count)
{
toSeries.Points[index].positionRel = dp.positionRel;
}
}
}
}
}
///
/// Called after the series was drawn.
///
/// Site interface of the control.
/// True if series was removed from collection.
[SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", Justification = "This parameter is used when compiling for the Microsoft version of Chart")]
internal bool UnPrepareData(ISite controlSite)
{
bool result = false;
// Process Renko chart type data calculations
if(RenkoChart.UnPrepareData(this))
{
result = true;
}
// Process ThreeLineBreak chart type data calculations
if(ThreeLineBreakChart.UnPrepareData(this))
{
result = true;
}
// Process Kagi chart type data calculations
if(KagiChart.UnPrepareData(this))
{
result = true;
}
// Process PointAndFigure chart type data calculations
if(PointAndFigureChart.UnPrepareData(this))
{
result = true;
}
// Undo all changes done for the collected slice support
if(PieChart.UnPrepareData(this))
{
result = true;
}
// Reset original value type which was temp. set to String
if(_isXValueIndexed)
{
_xValueType = indexedXValueType;
}
// Reset auro values only at design time
bool reset = false;
if(controlSite != null && controlSite.DesignMode)
{
reset = true;
}
ResetAutoValues(reset);
return result;
}
///
/// Reset auto calculated series values.
///
internal void ResetAutoValues()
{
ResetAutoValues(true);
}
///
/// Reset auto calculated series values.
///
/// Indicates that value types should be reset.
internal void ResetAutoValues(bool reset)
{
// If temporary data attribute is set - remove all data points
if(this.IsCustomPropertySet("TempDesignData"))
{
this.DeleteCustomProperty("TempDesignData");
// save the fake DataPoints for selector service
bool savePoints = true;
if (this.Chart != null && !this.Chart.IsDesignMode())
{
savePoints = false;
}
if ( savePoints )
{
fakeDataPoints.Clear();
foreach (DataPoint p in this.Points)
{
fakeDataPoints.Add(p);
}
}
this.Points.Clear();
}
// Reset series color
if(this.tempColorIsSet)
{
this.tempColorIsSet = false;
this.Color = Color.Empty;
}
// Reset series marker
if(this.tempMarkerStyleIsSet)
{
this.tempMarkerStyleIsSet = false;
this.MarkerStyle = MarkerStyle.None;
}
// Reset points color
foreach(DataPoint dataPoint in _points)
{
if(dataPoint.tempColorIsSet)
{
dataPoint.Color = Color.Empty;
}
}
// Reset value type to Auto (if not Serializing data)
if(reset)
{
if(this.Chart == null || this.Chart.serializing == false)
{
if(autoXValueType)
{
_xValueType = ChartValueType.Auto;
autoXValueType = false;
}
if(autoYValueType)
{
_yValueType = ChartValueType.Auto;
autoYValueType = false;
}
}
}
}
///
/// Called just before the data from the series to be used to perform these operations:
/// - apply palette colors to the data points
/// - fill empty data points
/// - provide fake data in design mode
/// - retrieving data from the DataSource
///
/// If true each data point will be assigned a color from the palette (if it's set)
internal void PrepareData(bool applyPaletteColors)
{
if(!this.IsVisible())
{
return;
}
// Series chart area name can be empty or a valid area name
Chart.ChartAreas.VerifyNameReference(this.ChartArea);
// Check if sereis data points have required number of Y values
if(this.Points.Count > 0 && this.Points[0].YValues.Length < this.YValuesPerPoint)
{
// Resize data points Y value(s) arrays
foreach(DataPoint dp in this.Points)
{
dp.ResizeYValueArray(this.YValuesPerPoint);
}
}
// Get series data source
bool fillTempData = false;
if(this.Points.Count == 0)
{
// If there is no points defined in design-time
if(Chart.IsDesignMode())
{
fillTempData = true;
}
else if(this.IsCustomPropertySet("UseDummyData"))
{
if(String.Compare(this["UseDummyData"], "True", StringComparison.OrdinalIgnoreCase) == 0)
{
fillTempData = true;
}
}
}
// Create dummy data only if there was no points
if(fillTempData)
{
if(this.IsXValueDateTime() || _xValueType == ChartValueType.String)
{
this.Points.DataBindXY(GetDummyData(_xValueType), GetDummyData(_yValueType));
}
else
{
double[] xValues = new double[] { 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 };
if(this.ChartType == SeriesChartType.Polar)
{
xValues = new double[] { 0.0, 45.0, 115.0, 145.0, 180.0, 220.0 };
}
this.Points.DataBindXY(xValues, GetDummyData(_yValueType));
}
// If point has more than one Y value - copy the data from first value
if(this.YValuesPerPoint > 1)
{
foreach(DataPoint point in this.Points)
{
for(int valueIndex = 1; valueIndex < this.YValuesPerPoint; valueIndex++)
{
point.YValues[valueIndex] = point.YValues[0];
}
if(this.YValuesPerPoint >= 2)
{
point.YValues[1] = point.YValues[0] / 2 - 1;
}
if(this.YValuesPerPoint >= 4)
{
point.YValues[2] = point.YValues[1] + (point.YValues[0] - point.YValues[1]) / 3;
point.YValues[3] = point.YValues[2] + (point.YValues[0] - point.YValues[1]) / 3;
}
if(this.YValuesPerPoint >= 6)
{
point.YValues[4] = point.YValues[2] + (point.YValues[3] - point.YValues[2]) / 2;
point.YValues[5] = point.YValues[2] + (point.YValues[3] - point.YValues[2]) / 3;
}
}
}
// Set data series attribute that data is temporary
this["TempDesignData"] = "true";
}
// If value type was not Auto detected - set it to double
if(_xValueType == ChartValueType.Auto)
{
_xValueType = ChartValueType.Double;
autoXValueType = true;
}
if(_yValueType == ChartValueType.Auto)
{
_yValueType = ChartValueType.Double;
autoYValueType = true;
}
// Use data point index as X value
indexedXValueType = _xValueType;
// Reset total Y value
_totalYvalue = double.NaN;
// Supress zero and negative values with logarithmic axis exceptions
if(this.Chart != null && this.Chart.chartPicture.SuppressExceptions)
{
// Get series axis
Axis axisY = this.Chart.ChartAreas[this.ChartArea].GetAxis(AxisName.Y, this.YAxisType, this.YSubAxisName);
foreach(DataPoint point in this.Points)
{
for(int yValueIndex = 0; yValueIndex < point.YValues.Length; yValueIndex++)
{
if(axisY.IsLogarithmic)
{
// Look for Y values less or equal to Zero
if(point.YValues[yValueIndex] <= 0.0)
{
point.YValues[yValueIndex] = 1.0;
point.IsEmpty = true;
}
}
// Check All Y values for NaN
if(double.IsNaN(point.YValues[yValueIndex]))
{
point.YValues[yValueIndex] = 0.0;
point.IsEmpty = true;
}
}
}
}
// Process Error Bar chart type data linking and calculations
ErrorBarChart.GetDataFromLinkedSeries(this);
ErrorBarChart.CalculateErrorAmount(this);
// Process Box chart type data calculations
BoxPlotChart.CalculateBoxPlotFromLinkedSeries(this);
// Process Renko chart type data calculations
RenkoChart.PrepareData(this);
// Process ThreeLineBreak chart type data calculations
ThreeLineBreakChart.PrepareData(this);
// Process Kagi chart type data calculations
KagiChart.PrepareData(this);
// Process PointAndFigure chart type data calculations
PointAndFigureChart.PrepareData(this);
// Check if Collected slice should be displayed in Pie/Doughnut charts
PieChart.PrepareData(this);
// Apply palette colors to the data points
if (applyPaletteColors)
{
this.ApplyPaletteColors();
}
}
#endregion
#region Series Properties
///
/// Data series name.
///
[
SRCategory("CategoryAttributeData"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_Name"),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public override string Name
{
get
{
return base.Name;
}
set
{
base.Name = value;
}
}
///
/// Member of the chart data source used to data bind to the X value of the series.
///
[
SRCategory("CategoryAttributeDataSource"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_ValueMemberX"),
DefaultValue(""),
#if !Microsoft_CONTROL
TypeConverter(Editors.SeriesDataFieldXConvertor.Convertor)
#else
TypeConverter(typeof(SeriesDataSourceMemberConverter))
#endif
]
public string XValueMember
{
get
{
return _dataSourceXMember;
}
set
{
if(value == "(none)")
{
_dataSourceXMember = String.Empty;
}
else
{
_dataSourceXMember = value;
}
// Reset data bound flag
if(this.Common!=null && this.Common.ChartPicture!=null)
{
this.Common.ChartPicture.boundToDataSource = false;
}
}
}
///
/// Members of the chart data source used to data bind to the Y values of the series.
///
[
SRCategory("CategoryAttributeDataSource"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_ValueMembersY"),
DefaultValue(""),
#if !Microsoft_CONTROL
TypeConverter(Editors.SeriesDataFieldYConvertor.Convertor),
Editor(Editors.SeriesDataFieldValueAxisUITypeEditor.Editor, Editors.SeriesDataFieldValueAxisUITypeEditor.Base)
#else
TypeConverter(typeof(SeriesDataSourceMemberConverter)),
Editor(Editors.SeriesDataSourceMemberValueAxisUITypeEditor.Editor, Editors.SeriesDataSourceMemberValueAxisUITypeEditor.Base)
#endif
]
public string YValueMembers
{
get
{
return _dataSourceYMembers;
}
set
{
if(value == "(none)")
{
_dataSourceYMembers = String.Empty;
}
else
{
_dataSourceYMembers = value;
}
// Reset data bound flag
if(this.Common != null && this.Common.ChartPicture!=null)
{
this.Common.ChartPicture.boundToDataSource = false;
}
}
}
///
/// Name of the Chart legend used by the series.
///
[
SRCategory("CategoryAttributeLegend"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_Legend"),
DefaultValue(""),
TypeConverter(typeof(SeriesLegendNameConverter))
]
public string Legend
{
get
{
return _legend;
}
set
{
if (value != _legend)
{
if (Chart != null && Chart.Legends != null)
{
Chart.Legends.VerifyNameReference(value);
}
_legend = value;
this.Invalidate(false, true);
}
}
}
///
/// The value type of the X axis.
///
[
SRCategory("CategoryAttributeData"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_XValueType"),
DefaultValue(ChartValueType.Auto),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public ChartValueType XValueType
{
get
{
return _xValueType;
}
set
{
_xValueType = value;
this.autoXValueType = false;
this.Invalidate(true, false);
}
}
///
/// Indicates whether a data point index (1,2,...) will be used for the X value.
///
[
SRCategory("CategoryAttributeData"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_XValueIndexed"),
DefaultValue(false),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public bool IsXValueIndexed
{
get
{
return _isXValueIndexed;
}
set
{
_isXValueIndexed = value;
this.Invalidate(true, false);
}
}
///
/// The value type of the Y axis.
///
[
SRCategory("CategoryAttributeData"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_YValueType"),
DefaultValue(ChartValueType.Auto),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute),
#endif
TypeConverter(typeof(SeriesYValueTypeConverter)),
]
public ChartValueType YValueType
{
get
{
return _yValueType;
}
set
{
_yValueType = value;
this.autoYValueType = false;
this.Invalidate(true, false);
}
}
///
/// Number of Y values stored for each Data Point.
///
[
SRCategory("CategoryAttributeData"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_YValuesPerPoint"),
DefaultValue(1),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public int YValuesPerPoint
{
get
{
// If number of Y value(s) is not set - get one from the chart type
if(this._checkPointsNumber && this.ChartTypeName.Length > 0 && this.Common != null)
{
_checkPointsNumber = false;
ChartTypeRegistry chartTypeRegistry = this.Common.ChartTypeRegistry;
IChartType chartType = chartTypeRegistry.GetChartType(this.ChartTypeName);
if(chartType.YValuesPerPoint > _yValuesPerPoint)
{
_yValuesPerPoint = chartType.YValuesPerPoint;
// Resize Y value(s) array of data points
if(_points.Count > 0)
{
// Resize data points Y value(s) arrays
foreach(DataPoint dp in _points)
{
dp.ResizeYValueArray(_yValuesPerPoint);
}
}
}
}
return _yValuesPerPoint;
}
set
{
// Check if argument is in range
if(value < 1 || value > 32)
{
throw (new ArgumentOutOfRangeException("value", SR.ExceptionDataSeriesYValueNumberInvalid));
}
_checkPointsNumber = true;
// Resize Y value(s) array of data points
if(_points.Count > 0)
{
// Resize data points Y value(s) arrays
foreach(DataPoint dp in _points)
{
dp.ResizeYValueArray(value);
}
}
_yValuesPerPoint = value;
this.Invalidate(true, false);
}
}
///
/// Collection of data points in the series.
///
[
SRCategory("CategoryAttributeData"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_Points"),
#if Microsoft_CONTROL
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
#else
Themeable(false),
PersistenceMode(PersistenceMode.InnerProperty),
#endif
Editor(Editors.DataPointCollectionEditor.Editor, Editors.DataPointCollectionEditor.Base)
]
public DataPointCollection Points
{
get
{
return _points;
}
}
///
/// Default properties of an empty data point.
///
[
SRCategory("CategoryAttributeEmptyPoints"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_EmptyPointStyle"),
#if Microsoft_CONTROL
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
#else
PersistenceMode(PersistenceMode.InnerProperty),
#endif
]
public DataPointCustomProperties EmptyPointStyle
{
get
{
return _emptyPointCustomProperties;
}
set
{
if (value.series == null && _emptyPointCustomProperties.series != null)
{
value.series = _emptyPointCustomProperties.series;
}
_emptyPointCustomProperties = value;
_emptyPointCustomProperties.pointCustomProperties = false;
_emptyPointCustomProperties.SetDefault(false);
_emptyPointCustomProperties.pointCustomProperties = true;
_emptyPointCustomProperties.Parent = this;
this.Invalidate(true, false);
}
}
///
/// Color palette to use.
///
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
SRDescription("DescriptionAttributePalette"),
DefaultValue(ChartColorPalette.None),
Editor(Editors.ColorPaletteEditor.Editor, Editors.ColorPaletteEditor.Base)
]
public ChartColorPalette Palette
{
get
{
return _colorPalette;
}
set
{
_colorPalette = value;
this.Invalidate(true, true);
}
}
///
/// Specify how often to display data point markers.
///
[
SRCategory("CategoryAttributeMarker"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_MarkerStep"),
DefaultValue(1)
]
public int MarkerStep
{
get
{
return _markersStep;
}
set
{
if(value <= 0)
{
throw(new ArgumentException( SR.ExceptionMarkerStepNegativeValue, "value"));
}
_markersStep = value;
this.Invalidate(true, false);
}
}
///
/// Shadow offset of series.
///
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
SRDescription("DescriptionAttributeShadowOffset"),
DefaultValue(0)
]
public int ShadowOffset
{
get
{
return _shadowOffset;
}
set
{
_shadowOffset = value;
this.Invalidate(true, true);
}
}
///
/// Shadow color of series.
///
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(typeof(Color), "128,0,0,0"),
SRDescription("DescriptionAttributeShadowColor"),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public Color ShadowColor
{
get
{
return _shadowColor;
}
set
{
_shadowColor = value;
this.Invalidate(true, true);
}
}
#if SUBAXES
///
/// Name of the Y sub-axis this series is attached to.
///
[
SRCategory("CategoryAttributeAxes"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_YSubAxisName"),
DefaultValue("")
]
public string YSubAxisName
{
get
{
return this._ySubAxisName;
}
set
{
this._ySubAxisName = value;
this.Invalidate(true, false);
}
}
///
/// Name of the X sub-axis this series is attached to.
///
[
SRCategory("CategoryAttributeAxes"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_XSubAxisName"),
DefaultValue("")
]
public string XSubAxisName
{
get
{
return this._xSubAxisName;
}
set
{
this._xSubAxisName = value;
this.Invalidate(true, false);
}
}
#else // SUBAXES
///
/// Name of the Y sub-axis this series is attached to.
///
[
SRCategory("CategoryAttributeAxes"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_YSubAxisName"),
DefaultValue(""),
System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "value")
]
internal string YSubAxisName
{
get
{
return string.Empty;
}
set
{
}
}
///
/// Name of the X sub-axis this series is attached to.
///
[
SRCategory("CategoryAttributeAxes"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_XSubAxisName"),
DefaultValue(""),
System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "value")
]
internal string XSubAxisName
{
get
{
return string.Empty;
}
set
{
}
}
#endif // SUBAXES
///
/// Axis type of horizontal axes.
///
[
SRCategory("CategoryAttributeAxes"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_XAxisType"),
DefaultValue(AxisType.Primary)
]
public AxisType XAxisType
{
get
{
return _xAxisType;
}
set
{
_xAxisType = value;
this.Invalidate(true, false);
}
}
///
/// Axis type of vertical axes.
///
[
SRCategory("CategoryAttributeAxes"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_YAxisType"),
DefaultValue(AxisType.Primary)
]
public AxisType YAxisType
{
get
{
return _yAxisType;
}
set
{
_yAxisType = value;
this.Invalidate(true, false);
}
}
///
/// Gets or sets a flag which indicates whether the series is enabled.
///
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(true),
SRDescription("DescriptionAttributeSeries_Enabled"),
NotifyParentPropertyAttribute(true),
ParenthesizePropertyNameAttribute(true),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public bool Enabled
{
get
{
return _enabled;
}
set
{
_enabled = value;
this.Invalidate(true, true);
}
}
///
/// Chart type used to draw the series.
///
[
SRCategory("CategoryAttributeChart"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_Type"),
DefaultValue(SeriesChartType.Column),
RefreshProperties(RefreshProperties.All),
Editor(Editors.ChartTypeEditor.Editor, Editors.ChartTypeEditor.Base)
]
public SeriesChartType ChartType
{
get
{
SeriesChartType type = SeriesChartType.Column;
if(String.Compare(this.ChartTypeName, ChartTypeNames.OneHundredPercentStackedArea, StringComparison.OrdinalIgnoreCase) == 0)
{
type = SeriesChartType.StackedArea100;
}
else if (String.Compare(this.ChartTypeName, ChartTypeNames.OneHundredPercentStackedBar, StringComparison.OrdinalIgnoreCase) == 0)
{
type = SeriesChartType.StackedBar100;
}
else if (String.Compare(this.ChartTypeName, ChartTypeNames.OneHundredPercentStackedColumn, StringComparison.OrdinalIgnoreCase) == 0)
{
type = SeriesChartType.StackedColumn100;
}
else
{
try
{
type = (SeriesChartType)Enum.Parse(typeof(SeriesChartType), this.ChartTypeName, true);
}
catch (ArgumentException)
{
}
}
return type;
}
set
{
this.ChartTypeName = Series.GetChartTypeName(value);
}
}
///
/// Chart type used to draw the series.
///
[
Browsable(false),
EditorBrowsableAttribute(EditorBrowsableState.Never),
SRCategory("CategoryAttributeChart"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_Type"),
DefaultValue(ChartTypeNames.Column),
TypeConverter(typeof(ChartTypeConverter)),
Editor(Editors.ChartTypeEditor.Editor, Editors.ChartTypeEditor.Base),
RefreshProperties(RefreshProperties.All),
SerializationVisibilityAttribute(SerializationVisibility.Hidden),
DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)
]
public string ChartTypeName
{
get
{
return _chartType;
}
set
{
if(_chartType != value && value.Length > 0)
{
if(Common != null)
{
ChartTypeRegistry chartTypeRegistry = Common.ChartTypeRegistry;
if(chartTypeRegistry != null)
{
IChartType type = chartTypeRegistry.GetChartType(value);
if(_yValuesPerPoint < type.YValuesPerPoint)
{
// Set minimum Y values number for the chart type
_yValuesPerPoint = type.YValuesPerPoint;
// Resize Y value(s) array of data points
if(_points.Count > 0)
{
// Resize data points Y value(s) arrays
foreach(DataPoint dp in _points)
{
dp.ResizeYValueArray(_yValuesPerPoint);
}
}
}
#if Microsoft_CONTROL
// Refresh Minimum and Maximum from data
// after recalc and set data
if(Chart != null && Chart.chartPicture != null)
{
Chart.chartPicture.ResetMinMaxFromData();
}
#endif
}
}
}
_chartType = value;
this.Invalidate(false, true);
}
}
///
/// Chart area in which this series is drawn.
///
[
SRCategory("CategoryAttributeChart"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_ChartArea"),
DefaultValue(""),
TypeConverter(typeof(SeriesAreaNameConverter))
]
public string ChartArea
{
get
{
return _chartArea;
}
set
{
if (value != _chartArea)
{
if (Chart != null && Chart.ChartAreas != null)
{
Chart.ChartAreas.VerifyNameReference(value);
}
_chartArea = value;
this.Invalidate(false, true);
}
}
}
/*
///
/// If set to true, each data point of the series will use a random color from the palette.
///
[
SRCategory("CategoryAttributeChart"),
Bindable(true),
SRDescription("DescriptionAttributeDataSeriesGroupID"),
PersistenceModeAttribute(PersistenceMode.Attribute),
DefaultValue("")
]
public string GroupID
{
get
{
return groupID;
}
set
{
groupID = value;
}
}
*/
///
/// Text of X axis label.
///
[
Browsable(false),
SRCategory("CategoryAttributeMisc"),
Bindable(true),
DefaultValue(""),
SRDescription("DescriptionAttributeAxisLabel"),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
override public string AxisLabel
{
get
{
return base.AxisLabel;
}
set
{
base.AxisLabel = value;
this.Invalidate(true, false);
}
}
///
/// Style of the SmartLabel.
///
[
Browsable(true),
SRCategory("CategoryAttributeLabel"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_SmartLabels"),
#if Microsoft_CONTROL
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
#else
PersistenceMode(PersistenceMode.InnerProperty),
#endif
]
public SmartLabelStyle SmartLabelStyle
{
get
{
return _smartLabelStyle;
}
set
{
value.chartElement = this;
_smartLabelStyle = value;
this.Invalidate(false, false);
}
}
///
/// Series font cache is reused by points.
///
/// The font cache.
internal FontCache FontCache
{
get { return _fontCache; }
}
#endregion
#region Invalidating method
///
/// Invalidate chart or just a chart area and/or legend when collection is changed
///
/// Invalidate chart area only.
/// Invalidate legend area only.
[SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", Justification = "This parameter is used when compiling for the Microsoft version of Chart")]
internal void Invalidate(bool invalidateAreaOnly, bool invalidateLegend)
{
#if Microsoft_CONTROL
if(Chart != null)
{
if(!invalidateAreaOnly)
{
this.Invalidate();
}
else
{
// Invalidate one chart area (area with this name may not exist)
try
{
Chart.ChartAreas[this.ChartArea].Invalidate();
}
catch(ArgumentException)
{
// occurs if the chart area is not found in the collection
}
// Invalidate legend
if(invalidateLegend && Chart.Legends.IndexOf(this.Legend) >= 0)
{
Chart.Legends[this.Legend].Invalidate(true);
}
}
}
#endif
}
#endregion
#region Series Enumeration
///
/// Series values formula type used in the keywords
///
internal enum SeriesValuesFormulaType
{
Total,
Average,
Maximum,
Minimum,
First,
Last
}
#endregion // Series Enumeration
#region IDisposable Members
///
/// Releases unmanaged and - optionally - managed resources
///
/// true to release both managed and unmanaged resources; false to release only unmanaged resources.
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (_fontCache != null)
{
_fontCache.Dispose();
_fontCache = null;
}
if (this._emptyPointCustomProperties != null)
{
this._emptyPointCustomProperties.Dispose();
this._emptyPointCustomProperties = null;
}
if (this._points != null)
{
this._points.Dispose();
this._points = null;
}
if (this.fakeDataPoints != null)
{
this.fakeDataPoints.Dispose();
this.fakeDataPoints = null;
}
}
base.Dispose(disposing);
}
#endregion
}
}