2695 lines
72 KiB
C#
2695 lines
72 KiB
C#
|
//-------------------------------------------------------------
|
|||
|
// <copyright company=<3D>Microsoft Corporation<6F>>
|
|||
|
// Copyright <20> 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
|
|||
|
}
|
|||
|
}
|