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

942 lines
28 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

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

//-------------------------------------------------------------
// <copyright company=Microsoft Corporation>
// Copyright © Microsoft Corporation. All Rights Reserved.
// </copyright>
//-------------------------------------------------------------
// @owner=alexgor, deliant
//=================================================================
// File: AxisLabels.cs
//
// Namespace: System.Web.UI.WebControls[Windows.Forms].Charting
//
// Classes: AxisLabels
//
// Purpose: Base class for the Axis class which defines axis
// labels related properties and methods.
//
// Reviewed: GS - August 8, 2002
// AG - August 8, 2002
//
//===================================================================
#region Used namespaces
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Data;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
#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;
#else
using System.Web;
using System.Web.UI;
using System.Web.UI.DataVisualization.Charting;
using System.Web.UI.DataVisualization.Charting.Data;
using System.Web.UI.DataVisualization.Charting.ChartTypes;
using System.Web.UI.DataVisualization.Charting.Utilities;
#endif
#endregion
#if Microsoft_CONTROL
namespace System.Windows.Forms.DataVisualization.Charting
#else
namespace System.Web.UI.DataVisualization.Charting
#endif
{
/// <summary>
/// The Axis class provides functionality for
/// drawing axis labels.
/// </summary>
public partial class Axis
{
#region Fields
// Custom Labels collection
private CustomLabelsCollection _customLabels = null;
#endregion
#region Axis labels properties
/// <summary>
/// Gets or sets the style of the label.
/// </summary>
[
SRCategory("CategoryAttributeLabels"),
Bindable(true),
NotifyParentPropertyAttribute(true),
SRDescription("DescriptionAttributeLabelStyle"),
#if Microsoft_CONTROL
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
#else
PersistenceMode(PersistenceMode.InnerProperty),
#endif
TypeConverter(typeof(NoNameExpandableObjectConverter))
]
public LabelStyle LabelStyle
{
get
{
return labelStyle;
}
set
{
labelStyle = value;
labelStyle.Axis = (Axis)this;
this.Invalidate();
}
}
/// <summary>
/// Gets a collection of custom labels.
/// </summary>
[
SRCategory("CategoryAttributeLabels"),
Bindable(true),
SRDescription("DescriptionAttributeCustomLabels"),
#if Microsoft_CONTROL
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
#else
PersistenceMode(PersistenceMode.InnerProperty),
#endif
Editor(Editors.ChartCollectionEditor.Editor, Editors.ChartCollectionEditor.Base)
]
public CustomLabelsCollection CustomLabels
{
get
{
return _customLabels;
}
}
#endregion
#region Axis labels methods
/// <summary>
/// Indicates that custom grid lines should be painted.
/// </summary>
/// <returns>Indicates that custom grid lines should be painted.</returns>
internal bool IsCustomGridLines()
{
if(this.CustomLabels.Count > 0)
{
// Check if at least one custom label has a flag set
foreach(CustomLabel label in this.CustomLabels)
{
if((label.GridTicks & GridTickTypes.Gridline) == GridTickTypes.Gridline)
{
return true;
}
}
}
return false;
}
/// <summary>
/// Indicates that custom tick marks should be painted.
/// </summary>
/// <returns>Indicates that custom tick marks should be painted.</returns>
internal bool IsCustomTickMarks()
{
if(this.CustomLabels.Count > 0)
{
// Check if at least one custom label has a flag set
foreach(CustomLabel label in this.CustomLabels)
{
if((label.GridTicks & GridTickTypes.TickMark) == GridTickTypes.TickMark)
{
return true;
}
}
}
return false;
}
/// <summary>
/// Gets the type of the axis.
/// </summary>
/// <value>The type of the axis.</value>
internal AxisType GetAxisType()
{
if (this.axisType == AxisName.X || this.axisType == AxisName.Y)
{
return AxisType.Primary;
}
else
{
return AxisType.Secondary;
}
}
/// <summary>
/// Gets the axis series.
/// </summary>
/// <returns></returns>
internal ArrayList GetAxisSeries()
{
ArrayList dataSeries = new ArrayList();
// check for attached series.
foreach (string seriesName in this.ChartArea.Series)
{
Series series = this.Common.DataManager.Series[seriesName];
if (this.axisType == AxisName.X || this.axisType == AxisName.X2)
{
if (series.XAxisType == this.GetAxisType())
{
dataSeries.Add(series);
}
}
else
{
if (series.YAxisType == this.GetAxisType())
{
dataSeries.Add(series);
}
}
}
return dataSeries;
}
/// <summary>
/// Gets the other (primary/secondary) axis.
/// </summary>
/// <returns></returns>
internal Axis GetOtherTypeAxis()
{
return ChartArea.GetAxis(
this.axisType,
this.GetAxisType() == AxisType.Primary ? AxisType.Secondary : AxisType.Primary,
String.Empty
);
}
/// <summary>
/// Checks if the other (primary/secondary) axis has custom labels labels.
/// These labels will be added if this axis has no series attached and no custom labels.
/// This works only on category axes.
/// </summary>
internal void PostFillLabels()
{
foreach (CustomLabel label in this.CustomLabels)
{
if (label.customLabel)
{
return;
}
}
// Labels are disabled for this axis
if (
!this.LabelStyle.Enabled ||
!this.enabled ||
!String.IsNullOrEmpty(((Axis)this).SubAxisName) ||
this.axisType == AxisName.Y ||
this.axisType == AxisName.Y2
)
{
return;
}
// check if no series attached.
if (this.GetAxisSeries().Count > 0)
{
return;
}
this.CustomLabels.Clear();
foreach (CustomLabel label in this.GetOtherTypeAxis().CustomLabels)
{
this.CustomLabels.Add(label.Clone());
}
}
/// <summary>
/// Fill labels from data from data manager or
/// from axis scale.
/// </summary>
/// <param name="removeFirstRow">True if first row of auto generated labels must be removed.</param>
internal void FillLabels(bool removeFirstRow)
{
#if SUBAXES
// Process all sub-axis
foreach(SubAxis subAxis in ((Axis)this).SubAxes)
{
subAxis.FillLabels(true);
}
#endif // SUBAXES
// Labels are disabled for this axis
if( !this.LabelStyle.Enabled || !this.enabled )
{
return;
}
// For circular chart area fill only Y axis labels
if(this.ChartArea != null && this.ChartArea.chartAreaIsCurcular)
{
if(this.axisType != AxisName.Y)
{
ICircularChartType type = this.ChartArea.GetCircularChartType();
if(type == null || !type.XAxisLabelsSupported())
{
return;
}
}
}
// Check if the custom labels exist
bool customLabelsFlag = false;
foreach( CustomLabel lab in CustomLabels )
{
if( lab.customLabel )
{
if( lab.RowIndex == 0 ||
this.ChartArea.chartAreaIsCurcular)
{
customLabelsFlag = true;
}
}
}
// Remove the first row of labels if custom labels not exist
if(removeFirstRow)
{
if( customLabelsFlag == false )
{
for( int index = 0; index < CustomLabels.Count; index++ )
{
if( CustomLabels[index].RowIndex == 0 )
{
CustomLabels.RemoveAt( index );
index = -1;
}
}
}
else
{
return;
}
}
// Get data series for this axis.
List<string> dataSeries = null;
switch( axisType )
{
case AxisName.X:
dataSeries = ChartArea.GetXAxesSeries( AxisType.Primary, ((Axis)this).SubAxisName );
break;
case AxisName.Y:
dataSeries = ChartArea.GetYAxesSeries( AxisType.Primary, ((Axis)this).SubAxisName );
break;
case AxisName.X2:
dataSeries = ChartArea.GetXAxesSeries( AxisType.Secondary, ((Axis)this).SubAxisName );
break;
case AxisName.Y2:
dataSeries = ChartArea.GetYAxesSeries( AxisType.Secondary, ((Axis)this).SubAxisName );
break;
}
// There aren't data series connected with this axis.
if( dataSeries.Count == 0 )
{
return;
}
//Let's convert the ArrayList of the series names into to string[]
string[] dataSeriesNames = new string[dataSeries.Count];
for (int i = 0; i < dataSeries.Count; i++)
dataSeriesNames[i] = (string)dataSeries[i];
// Check if series X values all set to zeros
bool seriesXValuesZeros = ChartHelper.SeriesXValuesZeros(this.Common, dataSeriesNames);
// Check if series is indexed (All X values zeros or IsXValueIndexed flag set)
bool indexedSeries = true;
if (!seriesXValuesZeros)
{
indexedSeries = ChartHelper.IndexedSeries(this.Common, dataSeriesNames);
}
// Show End Labels
int endLabels = 0;
if( labelStyle.IsEndLabelVisible )
{
endLabels = 1;
}
// Get chart type of the first series
IChartType chartType = Common.ChartTypeRegistry.GetChartType( ChartArea.GetFirstSeries().ChartTypeName );
bool fromSeries = false;
if( !chartType.RequireAxes )
{
return;
}
else if( axisType == AxisName.Y || axisType == AxisName.Y2 )
{
fromSeries = false;
}
else
{
fromSeries = true;
}
// X values from data points are not 0.
if (fromSeries && !ChartHelper.SeriesXValuesZeros(this.Common, dataSeries.ToArray()))
{
fromSeries = false;
}
// X values from data points are not 0.
if( fromSeries && ( labelStyle.GetIntervalOffset() != 0 || labelStyle.GetInterval() != 0 ) )
{
fromSeries = false;
}
// Get value type
ChartValueType valueType;
if( axisType == AxisName.X || axisType == AxisName.X2 )
{
// If X value is indexed the type is always String. So we use indexed type instead
valueType = Common.DataManager.Series[dataSeries[0]].indexedXValueType;
}
else
{
valueType = Common.DataManager.Series[dataSeries[0]].YValueType;
}
if( labelStyle.GetIntervalType() != DateTimeIntervalType.Auto &&
labelStyle.GetIntervalType() != DateTimeIntervalType.Number )
{
if (valueType != ChartValueType.Time &&
valueType != ChartValueType.Date &&
valueType != ChartValueType.DateTimeOffset)
{
valueType = ChartValueType.DateTime;
}
}
// ***********************************
// Pre calculate some values
// ***********************************
double viewMaximum = this.ViewMaximum;
double viewMinimum = this.ViewMinimum;
// ***********************************
// Labels are filled from data series.
// ***********************************
if( fromSeries )
{
int numOfPoints;
numOfPoints = Common.DataManager.GetNumberOfPoints( dataSeries.ToArray() );
// Show end labels
if( endLabels == 1 )
{
// min position
CustomLabels.Add( - 0.5, 0.5, ValueConverter.FormatValue(
this.Common.Chart,
this,
null,
0.0,
this.LabelStyle.Format,
valueType,
ChartElementType.AxisLabels),
false);
}
// Labels from point position
for( int point = 0; point < numOfPoints; point++ )
{
CustomLabels.Add( ((double)point)+ 0.5, ((double)point)+ 1.5,
ValueConverter.FormatValue(
this.Common.Chart,
this,
null,
point + 1,
this.LabelStyle.Format,
valueType,
ChartElementType.AxisLabels),
false);
}
// Show end labels
if( endLabels == 1 )
{
// max position
CustomLabels.Add( ((double)numOfPoints)+ 0.5, ((double)numOfPoints)+ 1.5,
ValueConverter.FormatValue(
this.Common.Chart,
this,
null,
numOfPoints + 1,
this.LabelStyle.Format,
valueType,
ChartElementType.AxisLabels),
false);
}
int pointIndx;
foreach( string seriesIndx in dataSeries )
{
// End labels enabled
if( endLabels == 1 )
pointIndx = 1;
else
pointIndx = 0;
// Set labels from data points labels
foreach( DataPoint dataPoint in Common.DataManager.Series[ seriesIndx ].Points )
{
// Find first row of labels
while( CustomLabels[pointIndx].RowIndex > 0 )
{
pointIndx++;
}
// Add X labels
if( axisType == AxisName.X || axisType == AxisName.X2 )
{
if( dataPoint.AxisLabel.Length > 0 )
{
CustomLabels[pointIndx].Text = dataPoint.AxisLabel;
}
}
pointIndx++;
}
}
}
// ***********************************
// Labels are filled from axis scale.
// ***********************************
else
{
if( viewMinimum == viewMaximum )
return;
double labValue; // Value, which will be converted to text and used for, labels.
double beginPosition; // Begin position for a label
double endPosition; // End position for a label
double start; // Start position for all labels
// Get first series attached to this axis
Series axisSeries = null;
if(axisType == AxisName.X || axisType == AxisName.X2)
{
List<string> seriesArray = ChartArea.GetXAxesSeries((axisType == AxisName.X) ? AxisType.Primary : AxisType.Secondary, ((Axis)this).SubAxisName);
if(seriesArray.Count > 0)
{
axisSeries = Common.DataManager.Series[seriesArray[0]];
if(axisSeries != null && !axisSeries.IsXValueIndexed)
{
axisSeries = null;
}
}
}
// ***********************************
// Check if the AJAX zooming and scrolling mode is enabled.
// Labels are filled slightly different in this case.
// ***********************************
DateTimeIntervalType offsetType = (labelStyle.GetIntervalOffsetType() == DateTimeIntervalType.Auto) ? labelStyle.GetIntervalType() : labelStyle.GetIntervalOffsetType();
// By default start is equal to minimum
start = viewMinimum;
// Adjust start position depending on the interval type
if(!this.ChartArea.chartAreaIsCurcular ||
this.axisType == AxisName.Y ||
this.axisType == AxisName.Y2 )
{
start = ChartHelper.AlignIntervalStart(start, labelStyle.GetInterval(), labelStyle.GetIntervalType(), axisSeries);
}
// Move start if there is start position
if( labelStyle.GetIntervalOffset() != 0 && axisSeries == null)
{
start += ChartHelper.GetIntervalSize(start, labelStyle.GetIntervalOffset(),
offsetType, axisSeries, 0, DateTimeIntervalType.Number, true, false);
}
// ***************************************
// Date type
// ***************************************
if( valueType == ChartValueType.DateTime ||
valueType == ChartValueType.Date ||
valueType == ChartValueType.Time ||
valueType == ChartValueType.DateTimeOffset ||
axisSeries != null)
{
double position = start;
double dateInterval;
// Too many labels
if ((viewMaximum - start) / ChartHelper.GetIntervalSize(start, labelStyle.GetInterval(), labelStyle.GetIntervalType(), axisSeries, 0, DateTimeIntervalType.Number, true) > ChartHelper.MaxNumOfGridlines)
return;
int counter = 0;
double endLabelMaxPosition = viewMaximum - ChartHelper.GetIntervalSize(viewMaximum, labelStyle.GetInterval(), labelStyle.GetIntervalType(), axisSeries, labelStyle.GetIntervalOffset(), offsetType, true) / 2f;
double endLabelMinPosition = viewMinimum + ChartHelper.GetIntervalSize(viewMinimum, labelStyle.GetInterval(), labelStyle.GetIntervalType(), axisSeries, labelStyle.GetIntervalOffset(), offsetType, true) / 2f;
while( (decimal)position <= (decimal)viewMaximum )
{
dateInterval = ChartHelper.GetIntervalSize(position, labelStyle.GetInterval(), labelStyle.GetIntervalType(), axisSeries, labelStyle.GetIntervalOffset(), offsetType, true);
labValue = position;
// For IsLogarithmic axes
if( this.IsLogarithmic )
{
labValue = Math.Pow( this.logarithmBase, labValue );
}
// Check if we do not exceed max number of elements
if (counter++ > ChartHelper.MaxNumOfGridlines)
{
break;
}
if (endLabels == 0 && position >= endLabelMaxPosition)
{
break;
}
beginPosition = position - dateInterval * 0.5;
endPosition = position + dateInterval * 0.5;
if(endLabels == 0 && position <= endLabelMinPosition)
{
position += dateInterval;
continue;
}
if( (decimal)beginPosition > (decimal)viewMaximum )
{
position += dateInterval;
continue;
}
// NOTE: Fixes issue #6466
// Following code is removed due to the issues caused by the rounding error
//if( (((decimal)beginPosition + (decimal)endPosition) / 2.0m) < (decimal)viewMinimum )
//{
// position += dateInterval;
// continue;
//}
//if ((decimal)viewMaximum < (((decimal)beginPosition + (decimal)endPosition) / 2m))
//{
// position += dateInterval;
// continue;
//}
string pointLabel = GetPointLabel( dataSeries, labValue, !seriesXValuesZeros, indexedSeries );
if( pointLabel.Length == 0 )
{
// Do not draw last label for indexed series
if( position <= this.maximum )
{
// Add a label to the collection
if( position != this.maximum || !Common.DataManager.Series[ dataSeries[0] ].IsXValueIndexed )
{
CustomLabels.Add( beginPosition,
endPosition,
ValueConverter.FormatValue(
this.Common.Chart,
this,
null,
labValue,
this.LabelStyle.Format,
valueType,
ChartElementType.AxisLabels),
false);
}
}
}
else
{
// Add a label to the collection
CustomLabels.Add( beginPosition,
endPosition,
pointLabel,
false);
}
position += dateInterval;
}
}
else
{
// ***************************************
// Scale value type
// ***************************************
// Show First label if Start Label position is used
if( start != viewMinimum )
endLabels = 1;
// Set labels
int labelCounter = 0;
for (double position = start - endLabels * labelStyle.GetInterval(); position < viewMaximum - 1.5 * labelStyle.GetInterval() * (1 - endLabels); position = (double)((decimal)position + (decimal)labelStyle.GetInterval()))
{
// Prevent endless loop that may be caused by very small interval
// and double/decimal rounding errors
++labelCounter;
if(labelCounter > ChartHelper.MaxNumOfGridlines)
{
break;
}
labValue = (double)((decimal)position + (decimal)labelStyle.GetInterval());
// This line is introduce because sometimes 0 value will appear as
// very small value close to zero.
double inter = Math.Log(labelStyle.GetInterval());
double valu = Math.Log(Math.Abs(labValue));
int digits = (int)Math.Abs(inter)+5;
if( digits > 15 )
{
digits = 15;
}
if( Math.Abs(inter) < Math.Abs(valu)-5 )
{
labValue = Math.Round(labValue,digits);
}
// Too many labels
if( ( viewMaximum - start ) / labelStyle.GetInterval() > ChartHelper.MaxNumOfGridlines )
{
return;
}
// For IsLogarithmic axes
if( this.IsLogarithmic )
labValue = Math.Pow( this.logarithmBase, labValue );
beginPosition = (double)((decimal)position + (decimal)labelStyle.GetInterval() * 0.5m);
endPosition = (double)((decimal)position + (decimal)labelStyle.GetInterval() * 1.5m);
if( (decimal)beginPosition > (decimal)viewMaximum )
{
continue;
}
// Show End label if Start Label position is used
// Use decimal type to solve rounding issues
if( (decimal)(( beginPosition + endPosition )/2.0) > (decimal)viewMaximum )
{
continue;
}
string pointLabel = GetPointLabel( dataSeries, labValue, !seriesXValuesZeros, indexedSeries );
if( pointLabel.Length > 15 && labValue < 0.000001)
{
labValue = 0.0;
}
if( pointLabel.Length == 0 )
{
// Do not draw last label for indexed series
if( !(Common.DataManager.Series[ dataSeries[0] ].IsXValueIndexed && position > this.maximum) )
{
// Add a label to the collection
CustomLabels.Add( beginPosition,
endPosition,
ValueConverter.FormatValue(
this.Common.Chart,
this,
null,
labValue,
this.LabelStyle.Format,
valueType,
ChartElementType.AxisLabels),
false);
}
}
else
{
// Add a label to the collection
CustomLabels.Add( beginPosition,
endPosition,
pointLabel,
false);
}
}
}
}
}
/// <summary>
/// This method checks if there is a data point which has value X equal
/// to valuePosition, and returns label from data point if such value exist.
/// If data point with this value not exists empty string will be returned.
/// If all data points have X value zero, index is used instead of X value.
/// </summary>
/// <param name="series">Data series</param>
/// <param name="valuePosition">A value which should be found in data points x values</param>
/// <param name="nonZeroXValues">Series X values are not zeros.</param>
/// <param name="indexedSeries">Series is indexed. All X values are zeros or IsXValueIndexed flag set.</param>
/// <returns>LabelStyle</returns>
private string GetPointLabel(
List<string> series,
double valuePosition,
bool nonZeroXValues,
bool indexedSeries
)
{
// Get max number of data points in the series
int maxPointCount = 0;
foreach (string seriesName in series)
{
Series ser = Common.DataManager.Series[seriesName];
maxPointCount = Math.Max(maxPointCount, ser.Points.Count);
}
// Check if axis only contains axis abels
bool allEmpty = true;
foreach( string seriesName in series )
{
// Get series by name
Series ser = Common.DataManager.Series[ seriesName ];
// Check if series has axis labels set
if ((axisType == AxisName.X || axisType == AxisName.X2) && (margin != 0 || maxPointCount == 1 || !this._autoMinimum) && !ser.IsXValueIndexed)
{
if( ser.Points[ 0 ].AxisLabel.Length > 0 && ser.Points[ ser.Points.Count - 1 ].AxisLabel.Length > 0 )
{
allEmpty = false;
}
}
// Try getting label from the point
if(!ser.noLabelsInPoints || (nonZeroXValues && indexedSeries))
{
string result = GetPointLabel( ser, valuePosition, nonZeroXValues, indexedSeries );
if(!String.IsNullOrEmpty(result))
{
return result;
}
}
// VSTS 140676: Serach for IndexedSeriesLabelsSourceAttr attribute
// to find if we have indexed series as source of formula generated nonindexed series.
String labelSeriesName = ser[DataFormula.IndexedSeriesLabelsSourceAttr];
if (!String.IsNullOrEmpty(labelSeriesName))
{
Series labelsSeries = Common.DataManager.Series[labelSeriesName];
if (labelsSeries != null)
{
string result = GetPointLabel(labelsSeries, valuePosition, nonZeroXValues, true);
if (!String.IsNullOrEmpty(result))
{
return result;
}
}
}
}
if( !allEmpty )
{
return " ";
}
else
{
return "";
}
}
/// <summary>
/// This method checks if there is a data point which has value X equal
/// to valuePosition, and returns label from data point if such value exist.
/// If data point with this value not exists empty string will be returned.
/// If all data points have X value zero, index is used instead of X value.
/// </summary>
/// <param name="series">Data series</param>
/// <param name="valuePosition">A value which should be found in data points x values</param>
/// <param name="nonZeroXValues">Series X values are not zeros.</param>
/// <param name="indexedSeries">Series is indexed. All X values are zeros or IsXValueIndexed flag set.</param>
/// <returns>LabelStyle</returns>
private string GetPointLabel(
Series series,
double valuePosition,
bool nonZeroXValues,
bool indexedSeries)
{
int pointIndx = 1;
if( axisType == AxisName.Y || axisType == AxisName.Y2 )
{
return "";
}
if( !(( axisType == AxisName.X && series.XAxisType == AxisType.Primary ) || ( axisType == AxisName.X2 && series.XAxisType == AxisType.Secondary )) )
{
#if SUBAXES
if(series.XSubAxisName != ((Axis)this).SubAxisName)
{
return "";
}
#endif // SUBAXES
return "";
}
// Loop through all series data points
foreach( DataPoint point in series.Points )
{
// If series is indexed (all X values are zeros or IsXValueIndexed flag set)
if( indexedSeries )
{
// If axis label position matches point index
if( valuePosition == pointIndx )
{
// Use X value if axis label is not set and X values in series are not zeros
if(point.AxisLabel.Length == 0 && nonZeroXValues)
{
return ValueConverter.FormatValue(
this.Common.Chart,
this,
null,
point.XValue,
this.LabelStyle.Format,
series.XValueType,
ChartElementType.AxisLabels);
}
// Return axis label from data point
return point.ReplaceKeywords(point.AxisLabel);
}
}
else
{
// Find x value using Data point X values
if( point.XValue == valuePosition )
{
// Return label
return point.ReplaceKeywords(point.AxisLabel);
}
}
pointIndx++;
}
return "";
}
#endregion
}
}