1184 lines
35 KiB
C#
1184 lines
35 KiB
C#
|
//-------------------------------------------------------------
|
|||
|
// <copyright company=<3D>Microsoft Corporation<6F>>
|
|||
|
// Copyright <20> Microsoft Corporation. All Rights Reserved.
|
|||
|
// </copyright>
|
|||
|
//-------------------------------------------------------------
|
|||
|
// @owner=alexgor, deliant
|
|||
|
//=================================================================
|
|||
|
// File: DataManager.cs
|
|||
|
//
|
|||
|
// Namespace: System.Web.UI.WebControls[Windows.Forms].Charting.Data
|
|||
|
//
|
|||
|
// Classes: DataManager
|
|||
|
//
|
|||
|
// Purpose: Series storage and manipulation class.
|
|||
|
//
|
|||
|
// Reviewed: AG - Aug 1, 2002; GS - Aug 7, 2002
|
|||
|
//
|
|||
|
//===================================================================
|
|||
|
|
|||
|
|
|||
|
#region Used namespaces
|
|||
|
|
|||
|
using System;
|
|||
|
using System.ComponentModel;
|
|||
|
using System.ComponentModel.Design;
|
|||
|
using System.Data;
|
|||
|
using System.Drawing;
|
|||
|
using System.Drawing.Design;
|
|||
|
|
|||
|
#if Microsoft_CONTROL
|
|||
|
|
|||
|
using System.Windows.Forms.DataVisualization.Charting;
|
|||
|
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;
|
|||
|
|
|||
|
|
|||
|
#else
|
|||
|
using System.Web.UI;
|
|||
|
using System.Web.UI.WebControls;
|
|||
|
using System.Web.UI.DataVisualization.Charting;
|
|||
|
using System.Web.UI.DataVisualization.Charting.Data;
|
|||
|
using System.Web.UI.DataVisualization.Charting.Utilities;
|
|||
|
using System.Web.UI.DataVisualization.Charting.ChartTypes;
|
|||
|
#endif
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#if Microsoft_CONTROL
|
|||
|
namespace System.Windows.Forms.DataVisualization.Charting.Data
|
|||
|
#else
|
|||
|
namespace System.Web.UI.DataVisualization.Charting.Data
|
|||
|
#endif
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// Data Manager.
|
|||
|
/// </summary>
|
|||
|
internal class DataManager : ChartElement, IServiceProvider
|
|||
|
{
|
|||
|
#region Fields
|
|||
|
// Series collection
|
|||
|
private SeriesCollection _series = null;
|
|||
|
|
|||
|
// Servise container reference
|
|||
|
internal IServiceContainer serviceContainer = null;
|
|||
|
|
|||
|
// Chart color palette
|
|||
|
private ChartColorPalette _colorPalette = ChartColorPalette.BrightPastel;
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Constructors and initialization
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Data manager public constructor
|
|||
|
/// </summary>
|
|||
|
/// <param name="container">Service container object.</param>
|
|||
|
public DataManager(IServiceContainer container)
|
|||
|
{
|
|||
|
if(container == null)
|
|||
|
{
|
|||
|
throw(new ArgumentNullException(SR.ExceptionInvalidServiceContainer));
|
|||
|
}
|
|||
|
serviceContainer = container;
|
|||
|
Common = new CommonElements(container);
|
|||
|
_series = new SeriesCollection(this);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Returns Data Manager service object.
|
|||
|
/// </summary>
|
|||
|
/// <param name="serviceType">Service type requested.</param>
|
|||
|
/// <returns>Data Manager service object.</returns>
|
|||
|
[EditorBrowsableAttribute(EditorBrowsableState.Never)]
|
|||
|
object IServiceProvider.GetService(Type serviceType)
|
|||
|
{
|
|||
|
if(serviceType == typeof(DataManager))
|
|||
|
{
|
|||
|
return this;
|
|||
|
}
|
|||
|
throw (new ArgumentException( SR.ExceptionDataManagerUnsupportedType(serviceType.ToString())));
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Initialize data manger object
|
|||
|
/// </summary>
|
|||
|
internal void Initialize()
|
|||
|
{
|
|||
|
// Attach to the Chart Picture painting events
|
|||
|
ChartImage chartPicture = (ChartImage)serviceContainer.GetService(typeof(ChartImage));
|
|||
|
chartPicture.BeforePaint += new EventHandler<ChartPaintEventArgs>(this.ChartPicture_BeforePaint);
|
|||
|
chartPicture.AfterPaint += new EventHandler<ChartPaintEventArgs>(this.ChartPicture_AfterPaint);
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Chart picture painting events hanlers
|
|||
|
|
|||
|
internal override void Invalidate()
|
|||
|
{
|
|||
|
base.Invalidate();
|
|||
|
|
|||
|
#if Microsoft_CONTROL
|
|||
|
if (Chart!=null)
|
|||
|
Chart.Invalidate();
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Event fired when chart picture is going to be painted.
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender">Sender object.</param>
|
|||
|
/// <param name="e">Event arguments.</param>
|
|||
|
private void ChartPicture_BeforePaint(object sender, ChartPaintEventArgs e)
|
|||
|
{
|
|||
|
// Prepare series for drawing
|
|||
|
int markerIndex = 1;
|
|||
|
for(int index = 0; index < this.Series.Count; index++)
|
|||
|
{
|
|||
|
Series series = this.Series[index];
|
|||
|
|
|||
|
// Reset series "X values are zeros" flag
|
|||
|
series.xValuesZerosChecked = false;
|
|||
|
series.xValuesZeros = false;
|
|||
|
|
|||
|
// Set series colors from palette
|
|||
|
IChartType chartType = e.CommonElements.ChartTypeRegistry.GetChartType(series.ChartTypeName);
|
|||
|
bool paletteColorsInPoints = chartType.ApplyPaletteColorsToPoints;
|
|||
|
// if the series palette is set the we can color all data points, even on column chart.
|
|||
|
if (series.Palette != ChartColorPalette.None)
|
|||
|
{
|
|||
|
paletteColorsInPoints = true;
|
|||
|
}
|
|||
|
|
|||
|
this.PrepareData(
|
|||
|
paletteColorsInPoints,
|
|||
|
series.Name);
|
|||
|
|
|||
|
// Clear temp. marker style
|
|||
|
if(series.tempMarkerStyleIsSet)
|
|||
|
{
|
|||
|
series.MarkerStyle = MarkerStyle.None;
|
|||
|
series.tempMarkerStyleIsSet = false;
|
|||
|
}
|
|||
|
|
|||
|
// Set marker style for chart types based on markes
|
|||
|
if(chartType.GetLegendImageStyle(series) == LegendImageStyle.Marker && series.MarkerStyle == MarkerStyle.None)
|
|||
|
{
|
|||
|
series.MarkerStyle = (MarkerStyle)markerIndex++;
|
|||
|
series.tempMarkerStyleIsSet = true;
|
|||
|
|
|||
|
if(markerIndex > 9)
|
|||
|
{
|
|||
|
markerIndex = 1;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Event fired after chart picture was painted.
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender">Sender object.</param>
|
|||
|
/// <param name="e">Event arguments.</param>
|
|||
|
private void ChartPicture_AfterPaint(object sender, ChartPaintEventArgs e)
|
|||
|
{
|
|||
|
Chart control = (Chart)serviceContainer.GetService(typeof(Chart));
|
|||
|
if(control != null)
|
|||
|
{
|
|||
|
// Clean up series after drawing
|
|||
|
for(int index = 0; index < this.Series.Count; index++)
|
|||
|
{
|
|||
|
Series series = this.Series[index];
|
|||
|
if(series.UnPrepareData(control.Site))
|
|||
|
{
|
|||
|
--index;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Series data preparation methods
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Apply palette colors to the data series if UsePaletteColors property is set.
|
|||
|
/// </summary>
|
|||
|
internal void ApplyPaletteColors()
|
|||
|
{
|
|||
|
ChartColorPalette palette = this.Palette;
|
|||
|
// switch to default pallette if is none and custom collors array is empty.
|
|||
|
if (palette == ChartColorPalette.None && this.PaletteCustomColors.Length == 0)
|
|||
|
{
|
|||
|
palette = ChartColorPalette.BrightPastel;
|
|||
|
}
|
|||
|
|
|||
|
// Get palette colors
|
|||
|
int colorIndex = 0;
|
|||
|
Color[] paletteColors = (palette == ChartColorPalette.None) ?
|
|||
|
this.PaletteCustomColors : ChartPaletteColors.GetPaletteColors(palette);
|
|||
|
|
|||
|
foreach (Series dataSeries in _series)
|
|||
|
{
|
|||
|
// Check if chart area name is valid
|
|||
|
bool validAreaName = false;
|
|||
|
if (Chart!=null)
|
|||
|
{
|
|||
|
validAreaName = Chart.ChartAreas.IsNameReferenceValid(dataSeries.ChartArea);
|
|||
|
}
|
|||
|
|
|||
|
// Change color of the series only if valid chart area name is specified
|
|||
|
if(validAreaName)
|
|||
|
{
|
|||
|
// Change color of the series only if default color is set
|
|||
|
if(dataSeries.Color == Color.Empty || dataSeries.tempColorIsSet)
|
|||
|
{
|
|||
|
dataSeries.color = paletteColors[colorIndex++];
|
|||
|
dataSeries.tempColorIsSet = true;
|
|||
|
if(colorIndex >= paletteColors.Length)
|
|||
|
{
|
|||
|
colorIndex = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Called just before the data from the series to be used to perform these operations:
|
|||
|
/// - apply palette colors to the data series
|
|||
|
/// - prepare data in series
|
|||
|
/// </summary>
|
|||
|
/// <param name="pointsApplyPaletteColors">If true each data point will be assigned a color from the palette (if it's set)</param>
|
|||
|
/// <param name="series">List of series indexes, which requires data preparation</param>
|
|||
|
internal void PrepareData(bool pointsApplyPaletteColors, params string[] series)
|
|||
|
{
|
|||
|
this.ApplyPaletteColors();
|
|||
|
|
|||
|
// Prepare data in series
|
|||
|
Chart control = (Chart)serviceContainer.GetService(typeof(Chart));
|
|||
|
if(control != null)
|
|||
|
{
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
this.Series[seriesName].PrepareData(pointsApplyPaletteColors);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Series Min/Max values methods
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// This method checks if data point should be skipped. This
|
|||
|
/// method will return true if data point is empty.
|
|||
|
/// </summary>
|
|||
|
/// <param name="point">Data point</param>
|
|||
|
/// <returns>This method returns true if data point is empty.</returns>
|
|||
|
private bool IsPointSkipped( DataPoint point )
|
|||
|
{
|
|||
|
if( point.IsEmpty )
|
|||
|
{
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets max number of data points in specified series.
|
|||
|
/// </summary>
|
|||
|
/// <param name="series">Series IDs</param>
|
|||
|
/// <returns>Maximum number of data points</returns>
|
|||
|
internal int GetNumberOfPoints(params string[] series)
|
|||
|
{
|
|||
|
int numberOfPoints = 0;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
numberOfPoints = Math.Max(numberOfPoints, this._series[seriesName].Points.Count);
|
|||
|
}
|
|||
|
return numberOfPoints;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets maximum Y value from many series
|
|||
|
/// </summary>
|
|||
|
/// <param name="valueIndex">Index of Y value to use</param>
|
|||
|
/// <param name="series">Series IDs</param>
|
|||
|
/// <returns>Maximum Y value</returns>
|
|||
|
internal double GetMaxYValue(int valueIndex, params string[] series)
|
|||
|
{
|
|||
|
double returnValue = Double.MinValue;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
foreach(DataPoint seriesPoint in this._series[seriesName].Points)
|
|||
|
{
|
|||
|
// The empty point
|
|||
|
if( IsPointSkipped( seriesPoint ) )
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if(!double.IsNaN(seriesPoint.YValues[valueIndex]))
|
|||
|
{
|
|||
|
returnValue = Math.Max(returnValue, seriesPoint.YValues[valueIndex]);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return returnValue;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Get Maximum value for Y and and Radius (Y2) ( used for bubble chart )
|
|||
|
/// </summary>
|
|||
|
/// <param name="area">Chart Area</param>
|
|||
|
/// <param name="series">Series IDs</param>
|
|||
|
/// <returns>Maximum Y value</returns>
|
|||
|
internal double GetMaxYWithRadiusValue( ChartArea area, params string[] series )
|
|||
|
{
|
|||
|
double returnValue = Double.MinValue;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
foreach(DataPoint seriesPoint in this._series[seriesName].Points)
|
|||
|
{
|
|||
|
// The empty point
|
|||
|
if( IsPointSkipped( seriesPoint ) )
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if(!double.IsNaN(seriesPoint.YValues[0]))
|
|||
|
{
|
|||
|
if (seriesPoint.YValues.Length > 1)
|
|||
|
{
|
|||
|
returnValue = Math.Max(returnValue, seriesPoint.YValues[0] + BubbleChart.AxisScaleBubbleSize(area.Common, area, seriesPoint.YValues[1], true));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
returnValue = Math.Max(returnValue, seriesPoint.YValues[0]);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return returnValue;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Get Maximum value for X and Radius (Y2) ( used for bubble chart )
|
|||
|
/// </summary>
|
|||
|
/// <param name="area">Chart Area</param>
|
|||
|
/// <param name="series">Series IDs</param>
|
|||
|
/// <returns>Maximum X value</returns>
|
|||
|
internal double GetMaxXWithRadiusValue( ChartArea area, params string[] series )
|
|||
|
{
|
|||
|
double returnValue = Double.MinValue;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
foreach(DataPoint seriesPoint in this._series[seriesName].Points)
|
|||
|
{
|
|||
|
// The empty point
|
|||
|
if( IsPointSkipped( seriesPoint ) )
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if(!double.IsNaN(seriesPoint.XValue))
|
|||
|
{
|
|||
|
if (seriesPoint.YValues.Length > 1)
|
|||
|
{
|
|||
|
returnValue = Math.Max(returnValue, seriesPoint.XValue + BubbleChart.AxisScaleBubbleSize(area.Common, area, seriesPoint.XValue, false));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
returnValue = Math.Max(returnValue, seriesPoint.XValue);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return returnValue;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Get Minimum value for X and Radius Y2 ( used for bubble chart )
|
|||
|
/// </summary>
|
|||
|
/// <param name="area">Chart Area</param>
|
|||
|
/// <param name="series">Series IDs</param>
|
|||
|
/// <returns>Minimum X value</returns>
|
|||
|
internal double GetMinXWithRadiusValue( ChartArea area, params string[] series )
|
|||
|
{
|
|||
|
double returnValue = Double.MaxValue;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
foreach(DataPoint seriesPoint in this._series[seriesName].Points)
|
|||
|
{
|
|||
|
// The empty point
|
|||
|
if( IsPointSkipped( seriesPoint ) )
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if(!double.IsNaN(seriesPoint.XValue))
|
|||
|
{
|
|||
|
if (seriesPoint.YValues.Length > 1)
|
|||
|
{
|
|||
|
returnValue = Math.Min(returnValue, seriesPoint.XValue - BubbleChart.AxisScaleBubbleSize(area.Common, area, seriesPoint.YValues[1], false));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
returnValue = Math.Min(returnValue, seriesPoint.XValue);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return returnValue;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets maximum Y value from many series
|
|||
|
/// </summary>
|
|||
|
/// <param name="series">Series IDs</param>
|
|||
|
/// <returns>Maximum Y value</returns>
|
|||
|
internal double GetMaxYValue(params string[] series)
|
|||
|
{
|
|||
|
double returnValue = Double.MinValue;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
foreach(DataPoint seriesPoint in this._series[seriesName].Points)
|
|||
|
{
|
|||
|
// The empty point
|
|||
|
if( IsPointSkipped( seriesPoint ) )
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
foreach( double y in seriesPoint.YValues )
|
|||
|
{
|
|||
|
if(!double.IsNaN(y))
|
|||
|
{
|
|||
|
returnValue = Math.Max(returnValue, y);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return returnValue;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets maximum X value from many series
|
|||
|
/// </summary>
|
|||
|
/// <param name="series">Series IDs</param>
|
|||
|
/// <returns>Maximum X value</returns>
|
|||
|
internal double GetMaxXValue(params string[] series)
|
|||
|
{
|
|||
|
double returnValue = Double.MinValue;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
foreach(DataPoint seriesPoint in this._series[seriesName].Points)
|
|||
|
{
|
|||
|
returnValue = Math.Max(returnValue, seriesPoint.XValue);
|
|||
|
}
|
|||
|
}
|
|||
|
return returnValue;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets minimum and maximum X value from many series.
|
|||
|
/// </summary>
|
|||
|
/// <param name="min">Returns maximum X value.</param>
|
|||
|
/// <param name="max">Returns minimum X value.</param>
|
|||
|
/// <param name="series">Series IDs</param>
|
|||
|
internal void GetMinMaxXValue(out double min, out double max, params string[] series)
|
|||
|
{
|
|||
|
max = Double.MinValue;
|
|||
|
min = Double.MaxValue;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
foreach(DataPoint seriesPoint in this._series[seriesName].Points)
|
|||
|
{
|
|||
|
max = Math.Max(max, seriesPoint.XValue);
|
|||
|
min = Math.Min(min, seriesPoint.XValue);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets minimum and maximum Y value from many series.
|
|||
|
/// </summary>
|
|||
|
/// <param name="valueIndex">Index of Y value to use.</param>
|
|||
|
/// <param name="min">Returns maximum Y value.</param>
|
|||
|
/// <param name="max">Returns minimum Y value.</param>
|
|||
|
/// <param name="series">Series IDs</param>
|
|||
|
internal void GetMinMaxYValue(int valueIndex, out double min, out double max, params string[] series)
|
|||
|
{
|
|||
|
max = Double.MinValue;
|
|||
|
min = Double.MaxValue;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
foreach(DataPoint seriesPoint in this._series[seriesName].Points)
|
|||
|
{
|
|||
|
// Skip empty point
|
|||
|
if( IsPointSkipped( seriesPoint ) )
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
double yValue = seriesPoint.YValues[valueIndex];
|
|||
|
if(!double.IsNaN(yValue))
|
|||
|
{
|
|||
|
max = Math.Max(max, yValue);
|
|||
|
min = Math.Min(min, yValue);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets minimum and maximum Y value from many series.
|
|||
|
/// </summary>
|
|||
|
/// <param name="min">Returns maximum Y value.</param>
|
|||
|
/// <param name="max">Returns minimum Y value.</param>
|
|||
|
/// <param name="series">Series IDs</param>
|
|||
|
internal void GetMinMaxYValue(out double min, out double max, params string[] series)
|
|||
|
{
|
|||
|
max = Double.MinValue;
|
|||
|
min = Double.MaxValue;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
foreach(DataPoint seriesPoint in this._series[seriesName].Points)
|
|||
|
{
|
|||
|
// Skip empty point
|
|||
|
if( IsPointSkipped( seriesPoint ) )
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// Iterate through all Y values
|
|||
|
foreach( double y in seriesPoint.YValues )
|
|||
|
{
|
|||
|
if(!double.IsNaN(y))
|
|||
|
{
|
|||
|
max = Math.Max(max, y);
|
|||
|
min = Math.Min(min, y);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets minimum and maximum Y value from many series.
|
|||
|
/// </summary>
|
|||
|
/// <param name="seriesList">Series objects list.</param>
|
|||
|
/// <param name="min">Returns maximum Y value.</param>
|
|||
|
/// <param name="max">Returns minimum Y value.</param>
|
|||
|
internal void GetMinMaxYValue(System.Collections.ArrayList seriesList, out double min, out double max)
|
|||
|
{
|
|||
|
max = Double.MinValue;
|
|||
|
min = Double.MaxValue;
|
|||
|
foreach(Series series in seriesList)
|
|||
|
{
|
|||
|
foreach(DataPoint seriesPoint in series.Points)
|
|||
|
{
|
|||
|
// Skip empty point
|
|||
|
if( IsPointSkipped( seriesPoint ) )
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// Iterate through all Y values
|
|||
|
foreach( double y in seriesPoint.YValues )
|
|||
|
{
|
|||
|
if(!double.IsNaN(y))
|
|||
|
{
|
|||
|
max = Math.Max(max, y);
|
|||
|
min = Math.Min(min, y);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets maximum stacked Y value from many series
|
|||
|
/// </summary>
|
|||
|
/// <param name="valueIndex">Index of Y value to use</param>
|
|||
|
/// <param name="series">Series IDs</param>
|
|||
|
/// <returns>Maximum stacked Y value</returns>
|
|||
|
internal double GetMaxStackedYValue(int valueIndex, params string[] series)
|
|||
|
{
|
|||
|
double returnValue = 0;
|
|||
|
double numberOfPoints = GetNumberOfPoints(series);
|
|||
|
for(int pointIndex = 0; pointIndex < numberOfPoints; pointIndex++)
|
|||
|
{
|
|||
|
double stackedMax = 0;
|
|||
|
double noStackedMax = 0;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
if(this._series[seriesName].Points.Count > pointIndex)
|
|||
|
{
|
|||
|
// Take chart type from the series
|
|||
|
ChartTypeRegistry chartTypeRegistry = (ChartTypeRegistry)serviceContainer.GetService(typeof(ChartTypeRegistry));
|
|||
|
IChartType chartType = chartTypeRegistry.GetChartType(this._series[seriesName].ChartTypeName);
|
|||
|
|
|||
|
// If stacked area
|
|||
|
if( !chartType.StackSign )
|
|||
|
continue;
|
|||
|
|
|||
|
if( chartType.Stacked )
|
|||
|
{
|
|||
|
if(this._series[seriesName].Points[pointIndex].YValues[valueIndex] > 0)
|
|||
|
{
|
|||
|
stackedMax += this._series[seriesName].Points[pointIndex].YValues[valueIndex];
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
noStackedMax = Math.Max(noStackedMax,this._series[seriesName].Points[pointIndex].YValues[valueIndex]);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
stackedMax = Math.Max(stackedMax, noStackedMax);
|
|||
|
returnValue = Math.Max(returnValue, stackedMax);
|
|||
|
}
|
|||
|
return returnValue;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets maximum Unsigned stacked Y value from many series ( Stacked Area chart )
|
|||
|
/// </summary>
|
|||
|
/// <param name="valueIndex">Index of Y value to use</param>
|
|||
|
/// <param name="series">Series IDs</param>
|
|||
|
/// <returns>Maximum stacked Y value</returns>
|
|||
|
internal double GetMaxUnsignedStackedYValue(int valueIndex, params string[] series)
|
|||
|
{
|
|||
|
double returnValue = 0;
|
|||
|
double maxValue = Double.MinValue;
|
|||
|
double numberOfPoints = GetNumberOfPoints(series);
|
|||
|
for(int pointIndex = 0; pointIndex < numberOfPoints; pointIndex++)
|
|||
|
{
|
|||
|
double stackedMax = 0;
|
|||
|
double noStackedMax = 0;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
if (this._series[seriesName].Points.Count > pointIndex)
|
|||
|
{
|
|||
|
// Take chart type from the series
|
|||
|
ChartTypeRegistry chartTypeRegistry = (ChartTypeRegistry)serviceContainer.GetService(typeof(ChartTypeRegistry));
|
|||
|
IChartType chartType = chartTypeRegistry.GetChartType(this._series[seriesName].ChartTypeName);
|
|||
|
|
|||
|
// If stacked column and bar
|
|||
|
if (chartType.StackSign || double.IsNaN(this._series[seriesName].Points[pointIndex].YValues[valueIndex]))
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if (chartType.Stacked)
|
|||
|
{
|
|||
|
maxValue = Double.MinValue;
|
|||
|
stackedMax += this._series[seriesName].Points[pointIndex].YValues[valueIndex];
|
|||
|
if (stackedMax > maxValue)
|
|||
|
maxValue = stackedMax;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
noStackedMax = Math.Max(noStackedMax, this._series[seriesName].Points[pointIndex].YValues[valueIndex]);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
maxValue = Math.Max(maxValue, noStackedMax);
|
|||
|
returnValue = Math.Max(returnValue, maxValue);
|
|||
|
}
|
|||
|
return returnValue;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets maximum stacked X value from many series
|
|||
|
/// </summary>
|
|||
|
/// <param name="series">Series IDs</param>
|
|||
|
/// <returns>Maximum stacked X value</returns>
|
|||
|
internal double GetMaxStackedXValue(params string[] series)
|
|||
|
{
|
|||
|
double returnValue = 0;
|
|||
|
double numberOfPoints = GetNumberOfPoints(series);
|
|||
|
for(int pointIndex = 0; pointIndex < numberOfPoints; pointIndex++)
|
|||
|
{
|
|||
|
double doubleIndexValue = 0;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
if (this._series[seriesName].Points.Count > pointIndex)
|
|||
|
{
|
|||
|
if (this._series[seriesName].Points[pointIndex].XValue > 0)
|
|||
|
{
|
|||
|
doubleIndexValue += this._series[seriesName].Points[pointIndex].XValue;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
returnValue = Math.Max(returnValue, doubleIndexValue);
|
|||
|
}
|
|||
|
return returnValue;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets minimum Y value from many series
|
|||
|
/// </summary>
|
|||
|
/// <param name="valueIndex">Index of Y value to use</param>
|
|||
|
/// <param name="series">Series IDs</param>
|
|||
|
/// <returns>Minimum Y value</returns>
|
|||
|
internal double GetMinYValue(int valueIndex, params string[] series)
|
|||
|
{
|
|||
|
double returnValue = Double.MaxValue;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
foreach(DataPoint seriesPoint in this._series[seriesName].Points)
|
|||
|
{
|
|||
|
// The empty point
|
|||
|
if( IsPointSkipped( seriesPoint ) )
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if(!double.IsNaN(seriesPoint.YValues[valueIndex]))
|
|||
|
{
|
|||
|
returnValue = Math.Min(returnValue, seriesPoint.YValues[valueIndex]);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return returnValue;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Get Minimum value for Y and and Radius (Y2) ( used for bubble chart )
|
|||
|
/// </summary>
|
|||
|
/// <param name="area">Chart Area</param>
|
|||
|
/// <param name="series">Series IDs</param>
|
|||
|
/// <returns>Minimum Y value</returns>
|
|||
|
internal double GetMinYWithRadiusValue( ChartArea area, params string[] series )
|
|||
|
{
|
|||
|
double returnValue = Double.MaxValue;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
foreach(DataPoint seriesPoint in this._series[seriesName].Points)
|
|||
|
{
|
|||
|
// The empty point
|
|||
|
if( IsPointSkipped( seriesPoint ) )
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if(!double.IsNaN(seriesPoint.YValues[0]))
|
|||
|
{
|
|||
|
if (seriesPoint.YValues.Length > 1)
|
|||
|
{
|
|||
|
returnValue = Math.Min(returnValue, seriesPoint.YValues[0] - BubbleChart.AxisScaleBubbleSize(area.Common, area, seriesPoint.YValues[1], true));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
returnValue = Math.Min(returnValue, seriesPoint.YValues[0]);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return returnValue;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets minimum Y value from many series
|
|||
|
/// </summary>
|
|||
|
/// <param name="series">Series IDs</param>
|
|||
|
/// <returns>Minimum Y value</returns>
|
|||
|
internal double GetMinYValue(params string[] series)
|
|||
|
{
|
|||
|
double returnValue = Double.MaxValue;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
foreach(DataPoint seriesPoint in this._series[seriesName].Points)
|
|||
|
{
|
|||
|
// The empty point
|
|||
|
if( IsPointSkipped( seriesPoint ) )
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
foreach(double y in seriesPoint.YValues)
|
|||
|
{
|
|||
|
if(!double.IsNaN(y))
|
|||
|
{
|
|||
|
returnValue = Math.Min(returnValue, y);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return returnValue;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets minimum X value from many series
|
|||
|
/// </summary>
|
|||
|
/// <param name="series">Series IDs</param>
|
|||
|
/// <returns>Minimum X value</returns>
|
|||
|
internal double GetMinXValue(params string[] series)
|
|||
|
{
|
|||
|
double returnValue = Double.MaxValue;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
foreach(DataPoint seriesPoint in this._series[seriesName].Points)
|
|||
|
{
|
|||
|
returnValue = Math.Min(returnValue, seriesPoint.XValue);
|
|||
|
}
|
|||
|
}
|
|||
|
return returnValue;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets minimum stacked Y value from many series
|
|||
|
/// </summary>
|
|||
|
/// <param name="valueIndex">Index of Y value to use</param>
|
|||
|
/// <param name="series">Series IDs</param>
|
|||
|
/// <returns>Minimum stacked Y value</returns>
|
|||
|
internal double GetMinStackedYValue(int valueIndex, params string[] series)
|
|||
|
{
|
|||
|
double returnValue = Double.MaxValue;
|
|||
|
double numberOfPoints = GetNumberOfPoints(series);
|
|||
|
for(int pointIndex = 0; pointIndex < numberOfPoints; pointIndex++)
|
|||
|
{
|
|||
|
double stackedMin = 0;
|
|||
|
double noStackedMin = 0;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
if(this._series[seriesName].Points.Count > pointIndex)
|
|||
|
{
|
|||
|
// Take chart type from the series
|
|||
|
ChartTypeRegistry chartTypeRegistry = (ChartTypeRegistry)serviceContainer.GetService(typeof(ChartTypeRegistry));
|
|||
|
IChartType chartType = chartTypeRegistry.GetChartType(this._series[seriesName].ChartTypeName);
|
|||
|
|
|||
|
// If stacked area
|
|||
|
if( !chartType.StackSign || double.IsNaN(this._series[seriesName].Points[pointIndex].YValues[valueIndex]))
|
|||
|
continue;
|
|||
|
|
|||
|
if( chartType.Stacked )
|
|||
|
{
|
|||
|
if(this._series[seriesName].Points[pointIndex].YValues[valueIndex] < 0)
|
|||
|
{
|
|||
|
stackedMin += this._series[seriesName].Points[pointIndex].YValues[valueIndex];
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
noStackedMin = Math.Min(noStackedMin,this._series[seriesName].Points[pointIndex].YValues[valueIndex]);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
stackedMin = Math.Min(stackedMin, noStackedMin);
|
|||
|
if( stackedMin == 0 )
|
|||
|
{
|
|||
|
stackedMin = this._series[series[0]].Points[this._series[series[0]].Points.Count - 1].YValues[valueIndex];
|
|||
|
}
|
|||
|
returnValue = Math.Min(returnValue, stackedMin);
|
|||
|
}
|
|||
|
return returnValue;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets minimum Unsigned stacked Y value from many series
|
|||
|
/// </summary>
|
|||
|
/// <param name="valueIndex">Index of Y value to use</param>
|
|||
|
/// <param name="series">Series IDs</param>
|
|||
|
/// <returns>Minimum stacked Y value</returns>
|
|||
|
internal double GetMinUnsignedStackedYValue(int valueIndex, params string[] series)
|
|||
|
{
|
|||
|
double returnValue = Double.MaxValue;
|
|||
|
double minValue = Double.MaxValue;
|
|||
|
double numberOfPoints = GetNumberOfPoints(series);
|
|||
|
for(int pointIndex = 0; pointIndex < numberOfPoints; pointIndex++)
|
|||
|
{
|
|||
|
double stackedMin = 0;
|
|||
|
double noStackedMin = 0;
|
|||
|
minValue = Double.MaxValue;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
if (this._series[seriesName].Points.Count > pointIndex)
|
|||
|
{
|
|||
|
// Take chart type from the series
|
|||
|
ChartTypeRegistry chartTypeRegistry = (ChartTypeRegistry)serviceContainer.GetService(typeof(ChartTypeRegistry));
|
|||
|
IChartType chartType = chartTypeRegistry.GetChartType(this._series[seriesName].ChartTypeName);
|
|||
|
|
|||
|
// If stacked column and bar
|
|||
|
if (chartType.StackSign || double.IsNaN(this._series[seriesName].Points[pointIndex].YValues[valueIndex]))
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if (chartType.Stacked)
|
|||
|
{
|
|||
|
if (this._series[seriesName].Points[pointIndex].YValues[valueIndex] < 0)
|
|||
|
{
|
|||
|
stackedMin += this._series[seriesName].Points[pointIndex].YValues[valueIndex];
|
|||
|
if (stackedMin < minValue)
|
|||
|
minValue = stackedMin;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
noStackedMin = Math.Min(noStackedMin, this._series[seriesName].Points[pointIndex].YValues[valueIndex]);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
minValue = Math.Min(noStackedMin, minValue);
|
|||
|
returnValue = Math.Min(returnValue, minValue);
|
|||
|
}
|
|||
|
return returnValue;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets minimum stacked X value from many series
|
|||
|
/// </summary>
|
|||
|
/// <param name="series">Series IDs</param>
|
|||
|
/// <returns>Minimum stacked X value</returns>
|
|||
|
internal double GetMinStackedXValue(params string[] series)
|
|||
|
{
|
|||
|
double returnValue = 0;
|
|||
|
double numberOfPoints = GetNumberOfPoints(series);
|
|||
|
for(int pointIndex = 0; pointIndex < numberOfPoints; pointIndex++)
|
|||
|
{
|
|||
|
double doubleIndexValue = 0;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
if(this._series[seriesName].Points[pointIndex].XValue < 0)
|
|||
|
{
|
|||
|
doubleIndexValue += this._series[seriesName].Points[pointIndex].XValue;
|
|||
|
}
|
|||
|
}
|
|||
|
returnValue = Math.Min(returnValue, doubleIndexValue);
|
|||
|
}
|
|||
|
return returnValue;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets maximum hundred percent stacked Y value
|
|||
|
/// </summary>
|
|||
|
/// <param name="supportNegative">Indicates that negative values are shown on the other side of the axis.</param>
|
|||
|
/// <param name="series">Series names</param>
|
|||
|
/// <returns>Maximum 100% stacked Y value</returns>
|
|||
|
internal double GetMaxHundredPercentStackedYValue(bool supportNegative, params string[] series)
|
|||
|
{
|
|||
|
double returnValue = 0;
|
|||
|
|
|||
|
// Convert array of series names into array of series
|
|||
|
Series[] seriesArray = new Series[series.Length];
|
|||
|
int seriesIndex = 0;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
seriesArray[seriesIndex++] = this._series[seriesName];
|
|||
|
}
|
|||
|
|
|||
|
// Loop through all dat points
|
|||
|
try
|
|||
|
{
|
|||
|
for(int pointIndex = 0; pointIndex < this._series[series[0]].Points.Count; pointIndex++)
|
|||
|
{
|
|||
|
// Calculate the total for all series
|
|||
|
double totalPerPoint = 0;
|
|||
|
double positiveTotalPerPoint = 0;
|
|||
|
foreach(Series ser in seriesArray)
|
|||
|
{
|
|||
|
if(supportNegative)
|
|||
|
{
|
|||
|
totalPerPoint += Math.Abs(ser.Points[pointIndex].YValues[0]);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
totalPerPoint += ser.Points[pointIndex].YValues[0];
|
|||
|
}
|
|||
|
|
|||
|
if(ser.Points[pointIndex].YValues[0] > 0 || supportNegative == false)
|
|||
|
{
|
|||
|
positiveTotalPerPoint += ser.Points[pointIndex].YValues[0];
|
|||
|
}
|
|||
|
}
|
|||
|
totalPerPoint = Math.Abs(totalPerPoint);
|
|||
|
|
|||
|
// Calculate percentage of total
|
|||
|
if(totalPerPoint != 0)
|
|||
|
{
|
|||
|
returnValue = Math.Max(returnValue,
|
|||
|
(positiveTotalPerPoint / totalPerPoint) * 100.0);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch(System.Exception)
|
|||
|
{
|
|||
|
throw (new InvalidOperationException(SR.ExceptionDataManager100StackedSeriesPointsNumeberMismatch));
|
|||
|
}
|
|||
|
|
|||
|
return returnValue;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets minimum hundred percent stacked Y value
|
|||
|
/// </summary>
|
|||
|
/// <param name="supportNegative">Indicates that negative values are shown on the other side of the axis.</param>
|
|||
|
/// <param name="series">Series names</param>
|
|||
|
/// <returns>Minimum 100% stacked Y value</returns>
|
|||
|
internal double GetMinHundredPercentStackedYValue(bool supportNegative, params string[] series)
|
|||
|
{
|
|||
|
double returnValue = 0.0;
|
|||
|
|
|||
|
// Convert array of series names into array of series
|
|||
|
Series[] seriesArray = new Series[series.Length];
|
|||
|
int seriesIndex = 0;
|
|||
|
foreach(string seriesName in series)
|
|||
|
{
|
|||
|
seriesArray[seriesIndex++] = this._series[seriesName];
|
|||
|
}
|
|||
|
|
|||
|
// Loop through all dat points
|
|||
|
try
|
|||
|
{
|
|||
|
for(int pointIndex = 0; pointIndex < this._series[series[0]].Points.Count; pointIndex++)
|
|||
|
{
|
|||
|
// Calculate the total for all series
|
|||
|
double totalPerPoint = 0;
|
|||
|
double negativeTotalPerPoint = 0;
|
|||
|
foreach(Series ser in seriesArray)
|
|||
|
{
|
|||
|
if(supportNegative)
|
|||
|
{
|
|||
|
totalPerPoint += Math.Abs(ser.Points[pointIndex].YValues[0]);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
totalPerPoint += ser.Points[pointIndex].YValues[0];
|
|||
|
}
|
|||
|
|
|||
|
if(ser.Points[pointIndex].YValues[0] < 0 || supportNegative == false)
|
|||
|
{
|
|||
|
negativeTotalPerPoint += ser.Points[pointIndex].YValues[0];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
totalPerPoint = Math.Abs(totalPerPoint);
|
|||
|
|
|||
|
// Calculate percentage of total
|
|||
|
if(totalPerPoint != 0)
|
|||
|
{
|
|||
|
returnValue = Math.Min(returnValue,
|
|||
|
(negativeTotalPerPoint / totalPerPoint) * 100.0);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch(System.Exception)
|
|||
|
{
|
|||
|
throw (new InvalidOperationException(SR.ExceptionDataManager100StackedSeriesPointsNumeberMismatch));
|
|||
|
}
|
|||
|
|
|||
|
return returnValue;
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region DataManager Properties
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Chart series collection.
|
|||
|
/// </summary>
|
|||
|
[
|
|||
|
SRCategory("CategoryAttributeData"),
|
|||
|
#if !Microsoft_CONTROL
|
|||
|
PersistenceMode(PersistenceMode.InnerProperty),
|
|||
|
#endif
|
|||
|
Editor(Editors.SeriesCollectionEditor.Editor, Editors.SeriesCollectionEditor.Base),
|
|||
|
Bindable(true)
|
|||
|
]
|
|||
|
public SeriesCollection Series
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return _series;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Color palette to use
|
|||
|
/// </summary>
|
|||
|
[
|
|||
|
SRCategory("CategoryAttributeAppearance"),
|
|||
|
Bindable(true),
|
|||
|
SRDescription("DescriptionAttributePalette"),
|
|||
|
#if !Microsoft_CONTROL
|
|||
|
PersistenceMode(PersistenceMode.InnerProperty),
|
|||
|
#endif
|
|||
|
DefaultValue(ChartColorPalette.BrightPastel),
|
|||
|
Editor(Editors.ColorPaletteEditor.Editor, Editors.ColorPaletteEditor.Base)
|
|||
|
]
|
|||
|
public ChartColorPalette Palette
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return _colorPalette;
|
|||
|
}
|
|||
|
set
|
|||
|
{
|
|||
|
_colorPalette = value;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Array of custom palette colors.
|
|||
|
private Color[] _paletteCustomColors = new Color[0];
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Array of custom palette colors.
|
|||
|
/// </summary>
|
|||
|
/// <remarks>
|
|||
|
/// When this custom colors array is non-empty the <b>Palette</b> property is ignored.
|
|||
|
/// </remarks>
|
|||
|
[
|
|||
|
SRCategory("CategoryAttributeAppearance"),
|
|||
|
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
|
|||
|
SerializationVisibilityAttribute(SerializationVisibility.Attribute),
|
|||
|
SRDescription("DescriptionAttributeDataManager_PaletteCustomColors"),
|
|||
|
TypeConverter(typeof(ColorArrayConverter))
|
|||
|
]
|
|||
|
public Color[] PaletteCustomColors
|
|||
|
{
|
|||
|
set
|
|||
|
{
|
|||
|
this._paletteCustomColors = value;
|
|||
|
}
|
|||
|
get
|
|||
|
{
|
|||
|
return this._paletteCustomColors;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#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 (_series != null)
|
|||
|
{
|
|||
|
_series.Dispose();
|
|||
|
_series = null;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
}
|
|||
|
}
|