Xamarin Public Jenkins (auto-signing) 536cd135cc Imported Upstream version 5.4.0.167
Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
2017-08-21 15:34:15 +00:00

2695 lines
72 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//-------------------------------------------------------------
// <copyright company=Microsoft Corporation>
// Copyright © Microsoft Corporation. All Rights Reserved.
// </copyright>
//-------------------------------------------------------------
// @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
/// <summary>
/// Chart axis type (Primary or Secondary).
/// </summary>
public enum AxisType
{
/// <summary>
/// Primary axis. For X axis - bottom, for Y axis - left.
/// </summary>
Primary,
/// <summary>
/// Secondary axis. For X axis - top, for Y axis - right.
/// </summary>
Secondary
};
/// <summary>
/// Sorting order (Ascending or Descending).
/// </summary>
public enum PointSortOrder
{
/// <summary>
/// Ascending sorting order
/// </summary>
Ascending,
/// <summary>
/// Descending sorting order
/// </summary>
Descending
}
#endregion
/// <summary>
/// Data series collection
/// </summary>
[
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<Series>
{
#region Constructors
/// <summary>
/// Data series collection object constructor.
/// </summary>
internal SeriesCollection(DataManager dataManager)
: base(dataManager)
{
}
#endregion
#region Methods
/// <summary>
/// Creates a new Series with the specified name and adds it to the collection.
/// </summary>
/// <param name="name">The new chart area name.</param>
/// <returns>New series</returns>
public Series Add(string name)
{
Series series = new Series(name);
this.Add(series);
return series;
}
/// <summary>
/// Fixes the name references of the item.
/// </summary>
/// <param name="item">Item to verify and fix.</param>
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
/// <summary>
/// Updates the Series' references to ChartAreas.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="Charting.NameReferenceChangedEventArgs"/> instance containing the event data.</param>
internal void ChartAreaNameReferenceChanged(object sender, NameReferenceChangedEventArgs e)
{
foreach (Series series in this)
if (series.ChartArea == e.OldName)
series.ChartArea = e.NewName;
}
/// <summary>
/// Updates the Series' references to Legends.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="Charting.NameReferenceChangedEventArgs"/> instance containing the event data.</param>
internal void LegendNameReferenceChanged(object sender, NameReferenceChangedEventArgs e)
{
foreach (Series series in this)
if (series.Legend == e.OldName)
series.Legend = e.NewName;
}
#endregion
}
/// <summary>
/// The class stores the data points and the default series properties.
/// </summary>
[
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
/// <summary>
/// Data point label text.
/// </summary>
internal string label = "";
/// <summary>
/// Data point X axis label text.
/// </summary>
internal string axisLabel = "";
/// <summary>
/// Data point label format string
/// </summary>
internal string labelFormat = "";
/// <summary>
/// If true shows point's value as a label.
/// </summary>
internal bool showLabelAsValue = false;
/// <summary>
/// Data point color
/// </summary>
internal Color color = Color.Empty;
/// <summary>
/// Data point border color
/// </summary>
internal Color borderColor = Color.Empty;
/// <summary>
/// Data point border style
/// </summary>
internal ChartDashStyle borderDashStyle = ChartDashStyle.Solid;
/// <summary>
/// Data point border width
/// </summary>
internal int borderWidth = 1;
/// <summary>
/// Data point marker border width
/// </summary>
internal int markerBorderWidth = 1;
/// <summary>
/// Data point background image
/// </summary>
internal string backImage = "";
/// <summary>
/// Data point background image drawing mode.
/// </summary>
internal ChartImageWrapMode backImageWrapMode = ChartImageWrapMode.Tile;
/// <summary>
/// Background image transparent color.
/// </summary>
internal Color backImageTransparentColor = Color.Empty;
/// <summary>
/// Background image alignment used by ClampUnscale drawing mode.
/// </summary>
internal ChartImageAlignmentStyle backImageAlignment = ChartImageAlignmentStyle.TopLeft;
/// <summary>
/// Data point background gradient type.
/// </summary>
internal GradientStyle backGradientStyle = GradientStyle.None;
/// <summary>
/// Data point background gradient end color
/// </summary>
internal Color backSecondaryColor = Color.Empty;
/// <summary>
/// Data point hatch style
/// </summary>
internal ChartHatchStyle backHatchStyle = ChartHatchStyle.None;
/// <summary>
/// Font cache for the fonts used in the Series and DataPoint
/// </summary>
private FontCache _fontCache = new FontCache();
/// <summary>
/// Data point font
/// </summary>
internal Font font = null;
/// <summary>
/// Data point line color
/// </summary>
internal Color fontColor = Color.Black;
/// <summary>
/// Data point font angle
/// </summary>
internal int fontAngle = 0;
/// <summary>
/// Data point marker style
/// </summary>
internal MarkerStyle markerStyle = MarkerStyle.None;
/// <summary>
/// Data point marker size
/// </summary>
internal int markerSize = 5;
/// <summary>
/// Data point marker image
/// </summary>
internal string markerImage = "";
/// <summary>
/// Data point marker image transparent color.
/// </summary>
internal Color markerImageTransparentColor = Color.Empty;
/// <summary>
/// Data point marker color
/// </summary>
internal Color markerColor = Color.Empty;
/// <summary>
/// Data point marker border color
/// </summary>
internal Color markerBorderColor = Color.Empty;
/// <summary>
/// The tooltip.
/// </summary>
internal string toolTip = "";
#if !Microsoft_CONTROL
/// <summary>
/// URL target of the area.
/// </summary>
internal string url = "";
/// <summary>
/// Other attributes of the area.
/// </summary>
internal string mapAreaAttributes = "";
/// <summary>
/// Other attributes of the area.
/// </summary>
internal string postbackValue = "";
#endif
/// <summary>
/// Indicates that item is shown in the legend.
/// </summary>
internal bool showInLegend = true;
/// <summary>
/// Text of the item in the legend
/// </summary>
internal string legendText = "";
/// <summary>
/// Tooltip of the item in the legend
/// </summary>
internal string legendToolTip = "";
/// <summary>
/// Data point label back color
/// </summary>
internal Color labelBackColor = Color.Empty;
/// <summary>
/// Data point label border color
/// </summary>
internal Color labelBorderColor = Color.Empty;
/// <summary>
/// Data point label border style
/// </summary>
internal ChartDashStyle labelBorderDashStyle = ChartDashStyle.Solid;
/// <summary>
/// Data point label border width
/// </summary>
internal int labelBorderWidth = 1;
/// <summary>
/// Tooltip of the data point label
/// </summary>
internal string labelToolTip = "";
#if !Microsoft_CONTROL
/// <summary>
/// URL target of the data point label.
/// </summary>
internal string labelUrl = "";
/// <summary>
/// Other attributes of the data point label.
/// </summary>
internal string labelMapAreaAttributes = "";
/// <summary>
/// Other attributes of the area.
/// </summary>
internal string labelPostbackValue = "";
/// <summary>
/// URL target of the item in the legend.
/// </summary>
internal string legendUrl = "";
/// <summary>
/// Other attributes of the legend map area.
/// </summary>
internal string legendMapAreaAttributes = "";
/// <summary>
/// Other attributes of the area.
/// </summary>
internal string legendPostbackValue = "";
#endif
#endregion
#region Constructors and initialization
/// <summary>
/// Initializes the default custom properties field.
/// </summary>
/// <returns>A DataPointCustomProperties initialized to defaults</returns>
private static DataPointCustomProperties InitializeDefaultCustomProperties()
{
DataPointCustomProperties customProperties = new DataPointCustomProperties(null, false);
customProperties.SetDefault(true);
customProperties.pointCustomProperties = true;
return customProperties;
}
/// <summary>
/// Series object constructor.
/// </summary>
public Series() : base(null, false)
{
InitProperties(null, 0);
}
/// <summary>
/// Series object constructor.
/// </summary>
/// <param name="name">Name of the data series</param>
public Series(string name) : base(null, false)
{
if(name == null)
{
throw (new ArgumentNullException(SR.ExceptionDataSeriesNameIsEmpty));
}
InitProperties(name, 0);
}
/// <summary>
/// Series object constructor.
/// </summary>
/// <param name="name">Name of the data series.</param>
/// <param name="yValues">Number of y values per data point.</param>
[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);
}
/// <summary>
/// Initialize series properties
/// </summary>
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
/// <summary>
/// Gets series caption that may not be the same as series name.
/// </summary>
/// <returns>Series caption string.</returns>
internal string GetCaption()
{
if (this.IsCustomPropertySet("SeriesCaption"))
{
return this["SeriesCaption"];
}
return this.Name;
}
/// <summary>
/// Gets custom points depth and gap depth from series properties.
/// </summary>
/// <param name="graph">Chart graphics.</param>
/// <param name="axis">Cate----cal axis.</param>
/// <param name="pointDepth">Returns point depth.</param>
/// <param name="pointGapDepth">Return point gap depth.</param>
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;
}
}
}
/// <summary>
/// Gets data point width in relative coordinates.
/// </summary>
/// <param name="graph">Chart graphics.</param>
/// <param name="axis">Axis object.</param>
/// <param name="interval">Current minimum axis interval.</param>
/// <param name="defaultWidth">Default width in percentage of interval.</param>
/// <returns>Point width.</returns>
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;
}
/// <summary>
/// Get chart type name by it's type
/// </summary>
/// <param name="type">Chart type.</param>
/// <returns>Chart type name.</returns>
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);
}
/// <summary>
/// Checks if Y values of the series represent date-time.
/// </summary>
/// <returns>True if date-time.</returns>
internal bool IsYValueDateTime()
{
if(this.YValueType == ChartValueType.Date ||
this.YValueType == ChartValueType.DateTime ||
this.YValueType == ChartValueType.Time ||
this.YValueType == ChartValueType.DateTimeOffset)
{
return true;
}
return false;
}
/// <summary>
/// Checks if X values of the series represent date-time.
/// </summary>
/// <returns>True if date-time.</returns>
internal bool IsXValueDateTime()
{
if(this.XValueType == ChartValueType.Date ||
this.XValueType == ChartValueType.DateTime ||
this.XValueType == ChartValueType.Time ||
this.XValueType == ChartValueType.DateTimeOffset)
{
return true;
}
return false;
}
/// <summary>
/// Checks if series is visible.
/// </summary>
/// <returns>True if series is visible.</returns>
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;
}
/// <summary>
/// Checks if series chart type uses a "Fast" mode chart type.
/// </summary>
/// <returns>True if series uses "Fast" mode chart type.</returns>
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;
}
/// <summary>
/// Throws exception if specified value type is not supported.
/// </summary>
/// <param name="type">Value type to check.</param>
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() ) ));
}
/// <summary>
/// Apply palette colors to the data series points if UsePaletteColors property is set.
/// </summary>
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;
}
}
}
}
/// <summary>
/// Gets design time dummy data.
/// </summary>
/// <param name="type">AxisName of the data to get.</param>
/// <returns>Dummy data for chart in design-time.</returns>
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;
}
/// <summary>
/// Returns total of the Y values.
/// </summary>
/// <returns>Y values total.</returns>
internal double GetTotalYValue()
{
return this.GetTotalYValue(0);
}
/// <summary>
/// Returns total of the Y values.
/// </summary>
/// <param name="yValueIndex">Index of the Y value to use</param>
/// <returns>Y values total.</returns>
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;
}
/// <summary>
/// Replaces predefined keyword inside the string with their values.
/// </summary>
/// <param name="strOriginal">Original string with keywords.</param>
/// <returns>Modified string.</returns>
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;
}
/// <summary>
/// Helper function which replaces one keyword.
/// </summary>
/// <param name="chart">Chart object reference.</param>
/// <param name="elementType">Chart element type.</param>
/// <param name="obj">Object being formatted.</param>
/// <param name="objTag">Additional object tag.</param>
/// <param name="strOriginal">Original string.</param>
/// <param name="keyword">Keyword to replace.</param>
/// <param name="formulaType">Formula used to calculate the value.</param>
/// <param name="valueType">AxisName of value.</param>
/// <param name="defaultFormat">Default format string.</param>
/// <returns>Result string.</returns>
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;
}
/// <summary>
/// Helper function which replaces one keyword.
/// </summary>
/// <param name="chart">Chart object reference.</param>
/// <param name="elementType">Chart element type.</param>
/// <param name="obj">Object being formatted.</param>
/// <param name="objTag">Additional object tag.</param>
/// <param name="strOriginal">Original string.</param>
/// <param name="keyword">Keyword to replace.</param>
/// <param name="value">Value to replace with.</param>
/// <param name="valueType">AxisName of value.</param>
/// <param name="defaultFormat">Default format string.</param>
/// <returns>Result string.</returns>
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
/// <summary>
/// Sorts the points in the series.
/// </summary>
/// <param name="pointSortOrder">Sorting order.</param>
/// <param name="sortBy">Value used for sorting (X, Y, Y2, ...).</param>
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);
}
/// <summary>
/// Sorts the points in the series.
/// </summary>
/// <param name="pointSortOrder">Sorting order.</param>
public void Sort(PointSortOrder pointSortOrder)
{
Sort(pointSortOrder, "Y");
}
/// <summary>
/// Sorts the points in the series using IComparer interface.
/// </summary>
/// <param name="comparer">IComparer interface.</param>
public void Sort(IComparer<DataPoint> 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
/// <summary>
/// Moves the position markers.
/// </summary>
/// <param name="fromSeries">From series.</param>
/// <param name="toSeries">To series.</param>
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;
}
}
}
}
}
/// <summary>
/// Called after the series was drawn.
/// </summary>
/// <param name="controlSite">Site interface of the control.</param>
/// <returns>True if series was removed from collection.</returns>
[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;
}
/// <summary>
/// Reset auto calculated series values.
/// </summary>
internal void ResetAutoValues()
{
ResetAutoValues(true);
}
/// <summary>
/// Reset auto calculated series values.
/// </summary>
/// <param name="reset">Indicates that value types should be reset.</param>
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;
}
}
}
}
/// <summary>
/// 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
/// </summary>
/// <param name="applyPaletteColors">If true each data point will be assigned a color from the palette (if it's set)</param>
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
/// <summary>
/// Data series name.
/// </summary>
[
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;
}
}
/// <summary>
/// Member of the chart data source used to data bind to the X value of the series.
/// </summary>
[
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;
}
}
}
/// <summary>
/// Members of the chart data source used to data bind to the Y values of the series.
/// </summary>
[
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;
}
}
}
/// <summary>
/// Name of the Chart legend used by the series.
/// </summary>
[
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);
}
}
}
/// <summary>
/// The value type of the X axis.
/// </summary>
[
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);
}
}
/// <summary>
/// Indicates whether a data point index (1,2,...) will be used for the X value.
/// </summary>
[
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);
}
}
/// <summary>
/// The value type of the Y axis.
/// </summary>
[
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);
}
}
/// <summary>
/// Number of Y values stored for each Data Point.
/// </summary>
[
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);
}
}
/// <summary>
/// Collection of data points in the series.
/// </summary>
[
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;
}
}
/// <summary>
/// Default properties of an empty data point.
/// </summary>
[
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);
}
}
/// <summary>
/// Color palette to use.
/// </summary>
[
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);
}
}
/// <summary>
/// Specify how often to display data point markers.
/// </summary>
[
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);
}
}
/// <summary>
/// Shadow offset of series.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
SRDescription("DescriptionAttributeShadowOffset"),
DefaultValue(0)
]
public int ShadowOffset
{
get
{
return _shadowOffset;
}
set
{
_shadowOffset = value;
this.Invalidate(true, true);
}
}
/// <summary>
/// Shadow color of series.
/// </summary>
[
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
/// <summary>
/// Name of the Y sub-axis this series is attached to.
/// </summary>
[
SRCategory("CategoryAttributeAxes"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_YSubAxisName"),
DefaultValue("")
]
public string YSubAxisName
{
get
{
return this._ySubAxisName;
}
set
{
this._ySubAxisName = value;
this.Invalidate(true, false);
}
}
/// <summary>
/// Name of the X sub-axis this series is attached to.
/// </summary>
[
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
/// <summary>
/// Name of the Y sub-axis this series is attached to.
/// </summary>
[
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
{
}
}
/// <summary>
/// Name of the X sub-axis this series is attached to.
/// </summary>
[
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
/// <summary>
/// Axis type of horizontal axes.
/// </summary>
[
SRCategory("CategoryAttributeAxes"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_XAxisType"),
DefaultValue(AxisType.Primary)
]
public AxisType XAxisType
{
get
{
return _xAxisType;
}
set
{
_xAxisType = value;
this.Invalidate(true, false);
}
}
/// <summary>
/// Axis type of vertical axes.
/// </summary>
[
SRCategory("CategoryAttributeAxes"),
Bindable(true),
SRDescription("DescriptionAttributeSeries_YAxisType"),
DefaultValue(AxisType.Primary)
]
public AxisType YAxisType
{
get
{
return _yAxisType;
}
set
{
_yAxisType = value;
this.Invalidate(true, false);
}
}
/// <summary>
/// Gets or sets a flag which indicates whether the series is enabled.
/// </summary>
[
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);
}
}
/// <summary>
/// Chart type used to draw the series.
/// </summary>
[
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);
}
}
/// <summary>
/// Chart type used to draw the series.
/// </summary>
[
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);
}
}
/// <summary>
/// Chart area in which this series is drawn.
/// </summary>
[
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);
}
}
}
/*
/// <summary>
/// If set to true, each data point of the series will use a random color from the palette.
/// </summary>
[
SRCategory("CategoryAttributeChart"),
Bindable(true),
SRDescription("DescriptionAttributeDataSeriesGroupID"),
PersistenceModeAttribute(PersistenceMode.Attribute),
DefaultValue("")
]
public string GroupID
{
get
{
return groupID;
}
set
{
groupID = value;
}
}
*/
/// <summary>
/// Text of X axis label.
/// </summary>
[
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);
}
}
/// <summary>
/// Style of the SmartLabel.
/// </summary>
[
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);
}
}
/// <summary>
/// Series font cache is reused by points.
/// </summary>
/// <value>The font cache.</value>
internal FontCache FontCache
{
get { return _fontCache; }
}
#endregion
#region Invalidating method
/// <summary>
/// Invalidate chart or just a chart area and/or legend when collection is changed
/// </summary>
/// <param name="invalidateAreaOnly">Invalidate chart area only.</param>
/// <param name="invalidateLegend">Invalidate legend area only.</param>
[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
/// <summary>
/// Series values formula type used in the keywords
/// </summary>
internal enum SeriesValuesFormulaType
{
Total,
Average,
Maximum,
Minimum,
First,
Last
}
#endregion // Series Enumeration
#region IDisposable Members
/// <summary>
/// Releases unmanaged and - optionally - managed resources
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
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
}
}