10638 lines
316 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using DevComponents.DotNetBar.Charts.Style;
namespace DevComponents.DotNetBar.Charts
{
/// <summary>
/// Represents the collection of ChartSeries.
/// </summary>
[Editor("DevComponents.Charts.Design.ChartSeriesCollectionEditor, DevComponents.Charts.Design, " +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public class ChartSeriesCollection : CustomNamedCollection<ChartSeries>
{
#region GetUniqueName
public string GetUniqueName()
{
return (GetUniqueName("Series"));
}
#endregion
}
public class ChartSeries : ChartVisualElement, ILegendItem
{
#region Constants
private const int StockHigh = 0;
private const int StockLow = 1;
private const int StockClose = 2;
private const int StockOpen = 3;
private const int StockMedian = 4;
#endregion
#region Private variables
private States _States;
private SeriesType _SeriesType = SeriesType.Point;
private SeriesPointCollection _SeriesPoints;
private PointData _PointData;
private PointData _EmptyPointData;
private PointData _StepPointData;
private object _DataSource;
private string _DataMember;
private DataBinder _DataBinder;
private string _DataPropertyNameSeries;
private string _DataPropertyNameX;
private CustomCollection<string> _DataPropertyNamesY;
private int _SeriesId;
private object _SeriesKey;
private ChartAxis _AxisX;
private ChartAxis _AxisY;
private int _BarOffset;
private int _BarWidth;
private double _BarWidthRatio;
private Tbool _BarShadingEnabled = Tbool.NotSet;
private BarFillRange _BarFillRange = BarFillRange.NotSet;
private BarLabelPosition _BarLabelPosition = BarLabelPosition.NotSet;
private Color[] _BarShadingColors;
private ChartLegendItemVisualStyles _ChartLegendItemVisualStyles;
private ChartSeriesVisualStyle _ChartSeriesVisualStyle;
private EffectiveStyle<ChartSeriesVisualStyle> _EffectiveChartSeriesStyle;
private DataLabelVisualStyle _DataLabelVisualStyle;
private EffectiveStyle<DataLabelVisualStyle> _EffectiveDataLabelStyle;
private Tbool _CrosshairEnabled = Tbool.NotSet;
private Tbool _CrosshairHighlightPoints = Tbool.NotSet;
private Tbool _CrosshairShowLabels = Tbool.NotSet;
private ScaleType _ScaleTypeX = ScaleType.NotSet;
private ScaleType _ScaleTypeY = ScaleType.NotSet;
private ScaleType _ActualScaleTypeX = ScaleType.NotSet;
private ScaleType _ActualScaleTypeY = ScaleType.NotSet;
private string _LegendText;
private ChartLegendItem _LegendItem;
private object _MinValueX;
private object _MinValueY;
private object _MaxValueX;
private object _MaxValueY;
private object _AreaBaseValue;
private bool _SeriesRangeChanged = true;
private SortedSeriesPoints _SortedSeriesPoints;
private object[] _EmptyValues;
private List<object> _QualitativeXValues;
private List<object> _QualitativeYValues;
private PointMarker _PointMarker;
private Image _PointMarkerImage;
private Image _PointMarkerEmptyImage;
private Image _PointMarkerHighlightImage;
private Point _PointOffset;
private int _GroupId;
private object _PlotData;
private double _DotPlotIndexValue = 1.0d;
private ChartIndicatorCollection _ChartIndicators;
private Point[] _ConvexHullPoints;
private double _BubbleScaleFactor = 1.0d;
private double _BubbleMaxPercentage = .25d;
private int _BubbleMinSize = 4;
private BubbleSizeMode _BubbleSizeMode = BubbleSizeMode.NotSet;
private BubbleIntensityMode _BubbleIntensityMode = BubbleIntensityMode.NotSet;
private ChartLineDisplayMode _ChartLineDisplayMode = ChartLineDisplayMode.NotSet;
private ChartLineAreaDisplayMode _ChartLineAreaDisplayMode = ChartLineAreaDisplayMode.NotSet;
private ConvexHullDisplayMode _ConvexHullDisplayMode = ConvexHullDisplayMode.NotSet;
private PointLabelDisplayMode _PointLabelDisplayMode = PointLabelDisplayMode.NotSet;
private StepLines _StepLines = StepLines.NotSet;
private StepLineMode _StepLineMode = StepLineMode.NotSet;
private StepLineMode _LastStepLineMode = StepLineMode.NotSet;
private Color _DefaultPaletteColor = Color.Empty;
private DataLabelCollection _DataLabels;
private int _PointLabelSkip;
private int _PointLabelMinDistance;
private HiLoBarType _HiLoBarType = HiLoBarType.Box;
private Rectangle _RenderBounds;
#endregion
#region Constructors
public ChartSeries()
: this(null, SeriesType.Point)
{
}
public ChartSeries(string name)
: this(name, SeriesType.Point)
{
}
public ChartSeries(SeriesType seriesType)
: this(null, seriesType)
{
}
public ChartSeries(string name, SeriesType seriesType)
{
Name = name;
SeriesType = seriesType;
InitDefaultStates();
_EffectiveChartSeriesStyle = new EffectiveStyle<ChartSeriesVisualStyle>(this);
_EffectiveDataLabelStyle = new EffectiveStyle<DataLabelVisualStyle>(this);
}
#endregion
#region InitDefaultStates
private void InitDefaultStates()
{
SetState(States.ShowInLegend, true);
SetState(States.ShowInParentLegend, true);
SetState(States.ShowCheckBoxInLegend, true);
SetState(States.ShowMarkerInLegend, true);
SetState(States.CheckedInLegend, true);
SetState(States.DisplayLinePointsOnTop, true);
SetState(States.StackQualitativePoints, true);
SetState(States.ShowOriginValueLabels, true);
}
#endregion
#region Public properties
#region ActualScaleTypeX
///<summary>
/// Gets the Actual X axis Scale Type (may be
/// different than XScaleType when XScaleType is 'Auto').
///</summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public ScaleType ActualScaleTypeX
{
get
{
if (IsRotated == false)
return (_ActualScaleTypeX);
return (_ActualScaleTypeY);
}
internal set { _ActualScaleTypeX = value; }
}
#endregion
#region ActualScaleTypeY
///<summary>
/// Gets the Actual Y axis Scale Type (may be
/// different than YScaleType when YScaleType is 'Auto').
///</summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public ScaleType ActualScaleTypeY
{
get
{
if (IsRotated == true)
return (_ActualScaleTypeX);
return (_ActualScaleTypeY);
}
internal set { _ActualScaleTypeY = value; }
}
#endregion
#region AreaBaseValue
///<summary>
/// Gets or sets the base, reference value for displaying Line/Spline/Step Areas.
///</summary>
[DefaultValue(null), Category("Data")]
[Description("Indicates the base, reference value for displaying Line/Spline/Step Areas.")]
[TypeConverter("DevComponents.Charts.Design.PointValueConverter," +
"DevComponents.Charts.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf")]
public object AreaBaseValue
{
get { return (_AreaBaseValue); }
set
{
if (value != _AreaBaseValue)
{
_AreaBaseValue = value;
OnPropertyChangedEx("AreaBaseValue", Style.VisualChangeType.Render);
}
}
}
#endregion
#region AxisX
/// <summary>
/// Gets a reference to the X-Axis associated with the series.
/// </summary>
[Category("Axis"), DefaultValue(null)]
[Description("Indicates the reference to the X-Axis associated with the series.")]
[TypeConverter(typeof(AxisTypeConverter))]
[Editor("DevComponents.Charts.Design.AxisListTypeEditor, DevComponents.Charts.Design, " +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public ChartAxis AxisX
{
get { return (_AxisX); }
set
{
if (value != _AxisX)
{
ChartXy chartXy = Parent as ChartXy;
if (value != null)
{
if (value.IsPrimaryAxis == false)
{
if (chartXy != null)
{
if (chartXy.AncillaryAxesX.Contains(value) == false)
{
throw new Exception("Cannot set the series XAxis. The axis is not primary " +
"or a member of the chart's AncillaryAxesX collection.");
}
}
}
}
if (_AxisX != null)
{
_AxisX.SeriesRangeChanged = true;
_AxisX.PropertyChanged -= AxisX_PropertyChanged;
}
else
{
if (chartXy != null)
chartXy.AxisX.SeriesRangeChanged = true;
}
_AxisX = value;
if (_AxisX != null)
{
_AxisX.SeriesRangeChanged = true;
_AxisX.PropertyChanged += AxisX_PropertyChanged;
}
else
{
if (chartXy != null)
chartXy.AxisX.SeriesRangeChanged = true;
}
OnPropertyChangedEx("AxisX", VisualChangeType.Layout);
}
}
}
void AxisX_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
InvalidateLayout();
}
#endregion
#region AxisY
/// <summary>
/// Gets a reference to the Y-Axis associated with the series.
/// </summary>
[Category("Axis"), DefaultValue(null)]
[Description("Indicates the reference to the Y-Axis associated with the series.")]
[Editor("DevComponents.Charts.Design.AxisListTypeEditor, DevComponents.Charts.Design, " +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public ChartAxis AxisY
{
get { return (_AxisY); }
set
{
if (value != _AxisY)
{
ChartXy chartXy = Parent as ChartXy;
if (value != null)
{
if (value.IsPrimaryAxis == false)
{
if (chartXy != null)
{
if (chartXy.AncillaryAxesY.Contains(value) == false)
{
throw new Exception("Cannot set the series YAxis. The axis is not primary " +
"or a member of the chart's AncillaryAxesY collection.");
}
}
}
}
if (_AxisY != null)
{
_AxisY.SeriesRangeChanged = true;
_AxisY.PropertyChanged -= AxisY_PropertyChanged;
}
else
{
if (chartXy != null)
chartXy.AxisY.SeriesRangeChanged = true;
}
_AxisY = value;
if (_AxisY != null)
{
_AxisY.SeriesRangeChanged = true;
_AxisY.PropertyChanged += AxisY_PropertyChanged;
}
else
{
if (chartXy != null)
chartXy.AxisY.SeriesRangeChanged = true;
}
OnPropertyChangedEx("AxisY", VisualChangeType.Layout);
}
}
}
void AxisY_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
InvalidateLayout();
}
#endregion
#region BarFillRange
/// <summary>
/// Gets or sets how series bars are filled (either according to
/// each individual bar range, or the entire series range).
/// </summary>
[DefaultValue(BarFillRange.NotSet), Category("Bar Display")]
[Description("Indicates how series bars are filled (either according to each individual bar range, or the entire series range).")]
public BarFillRange BarFillRange
{
get { return (_BarFillRange); }
set
{
if (value != _BarFillRange)
{
_BarFillRange = value;
OnPropertyChangedEx("BarFillRange", VisualChangeType.Render);
}
}
}
#endregion
#region BarLabelPosition
/// <summary>
/// Gets or sets the position of bar series labels (default is Center).
/// </summary>
[DefaultValue(BarLabelPosition.NotSet), Category("Bar Display")]
[Description("Indicates the position of bar series labels (default is Center).")]
public BarLabelPosition BarLabelPosition
{
get { return (_BarLabelPosition); }
set
{
if (value != _BarLabelPosition)
{
_BarLabelPosition = value;
OnPropertyChangedEx("BarLabelPosition", VisualChangeType.Layout);
}
}
}
#endregion
#region BarShadingEnabled
///<summary>
/// Gets or sets whether Bar shading is enabled for Horizontal and Vertical Bar series.
///</summary>
[DefaultValue(Tbool.NotSet), Category("Bar Display")]
[Description("Indicates whether Bar shading is enabled for Horizontal and Vertical Bar series.")]
public Tbool BarShadingEnabled
{
get { return (_BarShadingEnabled); }
set
{
if (value != _BarShadingEnabled)
{
_BarShadingEnabled = value;
OnPropertyChangedEx("BarShadingEnabled", VisualChangeType.Render);
}
}
}
#endregion
#region BarWidthRatio
/// <summary>
/// Gets or sets the ratio of bar width to bar spacing within
/// the same series (defaults to 2 - bar is twice as wide as spacing).
/// </summary>
[DefaultValue(0d), Category("Bar Display")]
[Description("Indicates the ratio of bar width to bar spacing within the same series (defaults to 2 - bar is twice as wide as spacing).")]
public double BarWidthRatio
{
get { return (_BarWidthRatio); }
set
{
if (value != _BarWidthRatio)
{
if (value < 0)
throw new ArgumentException("Value must be > 0");
_BarWidthRatio = value;
OnPropertyChangedEx("BarWidthRatio", VisualChangeType.Layout);
}
}
}
#endregion
#region BubbleIntensityMode
/// <summary>
/// Gets or sets the mode used to determine bubble intensities.
/// </summary>
[DefaultValue(BubbleIntensityMode.NotSet), Category("Display")]
[Description("Indicates the mode used to determine bubble intensities.")]
public BubbleIntensityMode BubbleIntensityMode
{
get { return (_BubbleIntensityMode); }
set
{
if (value != _BubbleIntensityMode)
{
_BubbleIntensityMode = value;
OnPropertyChangedEx("BubbleIntensityMode", VisualChangeType.Render);
}
}
}
#endregion
#region BubbleMaxPercentage
/// <summary>
/// Gets or sets the max percentage of the display
/// area used to calculate series bubble sizes (default is .25).
/// </summary>
[DefaultValue(0.25d), Category("Display")]
[Description("Indicates the max percentage of the display area used to calculate series bubble sizes (default is .25).")]
public double BubbleMaxPercentage
{
get { return (_BubbleMaxPercentage); }
set
{
if (value != _BubbleMaxPercentage)
{
if (value <= 0 || value > 1)
throw new ArgumentException("Value must be between 0 and 1");
_BubbleMaxPercentage = value;
OnPropertyChangedEx("BubbleMaxPercentage", VisualChangeType.Layout);
}
}
}
#endregion
#region BubbleMinSize
/// <summary>
/// Gets or sets the minimum series bubble size (in pixels) Default is 4.
/// </summary>
[DefaultValue(4), Category("Display")]
[Description("Indicates the minimum series bubble size (in pixels). Default is 4.")]
public int BubbleMinSize
{
get { return (_BubbleMinSize); }
set
{
if (value != _BubbleMinSize)
{
if (value < 0)
throw new ArgumentException("Value must be > 0");
_BubbleMinSize = value;
OnPropertyChangedEx("BubbleMinSize", VisualChangeType.Layout);
}
}
}
#endregion
#region BubbleScaleFactor
/// <summary>
/// Gets or sets the Scale Factor used to calculate series bubble sizes.
/// </summary>
[DefaultValue(1.0d), Category("Display")]
[Description("Indicates the Scale Factor used to calculate series bubble sizes.")]
public double BubbleScaleFactor
{
get { return (_BubbleScaleFactor); }
set
{
if (value != _BubbleScaleFactor)
{
_BubbleScaleFactor = value;
OnPropertyChangedEx("BubbleScaleFactor", VisualChangeType.Layout);
}
}
}
#endregion
#region BubbleSizeMode
/// <summary>
/// Gets or sets the mode used to calculate series bubble sizes.
/// </summary>
[DefaultValue(BubbleSizeMode.NotSet), Category("Display")]
[Description("Indicates the mode used to calculate series bubble sizes.")]
public BubbleSizeMode BubbleSizeMode
{
get { return (_BubbleSizeMode); }
set
{
if (value != _BubbleSizeMode)
{
_BubbleSizeMode = value;
OnPropertyChangedEx("BubbleSizeMode", VisualChangeType.Render);
}
}
}
#endregion
#region ChartIndicators
///<summary>
/// Gets a reference to the Chart Indicators collection.
///</summary>
[DefaultValue(null), Category("Appearance")]
[Description("Indicates the Chart Indicators collection.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ChartIndicatorCollection ChartIndicators
{
get
{
if (_ChartIndicators == null)
{
_ChartIndicators = new ChartIndicatorCollection();
_ChartIndicators.CollectionChanged += ChartIndicators_CollectionChanged;
}
return (_ChartIndicators);
}
internal set
{
if (_ChartIndicators != null)
_ChartIndicators.CollectionChanged -= ChartIndicators_CollectionChanged;
_ChartIndicators = value;
if (_ChartIndicators != null)
_ChartIndicators.CollectionChanged += ChartIndicators_CollectionChanged;
}
}
#region ChartIndicators_CollectionChanged
void ChartIndicators_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
bool updateLayout = false;
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (ChartIndicator ci in e.NewItems)
{
if (ci.ShowInLegend == true || ci.ShowInParentLegend == true)
updateLayout = true;
ci.Parent = this;
}
break;
case NotifyCollectionChangedAction.Replace:
foreach (ChartIndicator ci in e.OldItems)
{
if (ci.ShowInLegend == true || ci.ShowInParentLegend == true)
updateLayout = true;
ci.Parent = null;
}
foreach (ChartIndicator ci in e.NewItems)
{
if (ci.ShowInLegend == true || ci.ShowInParentLegend == true)
updateLayout = true;
ci.Parent = this;
}
break;
case NotifyCollectionChangedAction.Remove:
foreach (ChartIndicator ci in e.OldItems)
{
if (ci.ShowInLegend == true || ci.ShowInParentLegend == true)
updateLayout = true;
ci.Parent = null;
}
break;
}
if (updateLayout == true)
InvalidateLayout();
else
InvalidateRender();
}
#endregion
#endregion
#region ChartLegendItemVisualStyles
/// <summary>
/// Gets or sets the visual styles for the Legend item.
/// </summary>
[Category("Style")]
[Description("Indicates the visual styles for the Legend item.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ChartLegendItemVisualStyles ChartLegendItemVisualStyles
{
get
{
if (_ChartLegendItemVisualStyles == null)
{
_ChartLegendItemVisualStyles = new ChartLegendItemVisualStyles();
StyleVisualChangeHandler(null, _ChartLegendItemVisualStyles);
}
return (_ChartLegendItemVisualStyles);
}
set
{
if (_ChartLegendItemVisualStyles != value)
{
ChartLegendItemVisualStyles oldValue = _ChartLegendItemVisualStyles;
_ChartLegendItemVisualStyles = value;
OnStyleChanged("ChartLegendItemVisualStyles", oldValue, value);
if (oldValue != null)
oldValue.Dispose();
}
}
}
#endregion
#region ChartLineAreaDisplayMode
/// <summary>
/// Gets or sets the Line 'Area' display mode.
/// </summary>
[DefaultValue(ChartLineAreaDisplayMode.NotSet), Category("Display")]
[Description("Indicates the Line ChartType display mode.")]
[Editor("DevComponents.Charts.Design.FlagsEnumUIEditor, DevComponents.Charts.Design, " +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public ChartLineAreaDisplayMode ChartLineAreaDisplayMode
{
get { return (_ChartLineAreaDisplayMode); }
set
{
if (value != _ChartLineAreaDisplayMode)
{
_ChartLineAreaDisplayMode = value;
OnPropertyChangedEx("ChartLineAreaDisplayMode", VisualChangeType.Render);
}
}
}
#endregion
#region ChartLineDisplayMode
/// <summary>
/// Gets or sets the Line ChartType display mode.
/// </summary>
[DefaultValue(ChartLineDisplayMode.NotSet), Category("Display")]
[Description("Indicates the Line ChartType display mode.")]
[Editor("DevComponents.Charts.Design.FlagsEnumUIEditor, DevComponents.Charts.Design, " +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public ChartLineDisplayMode ChartLineDisplayMode
{
get { return (_ChartLineDisplayMode); }
set
{
if (value != _ChartLineDisplayMode)
{
_ChartLineDisplayMode = value;
_SortedSeriesPoints = null;
OnPropertyChangedEx("ChartLineDisplayMode", VisualChangeType.Render);
}
}
}
#endregion
#region ChartSeriesVisualStyle
/// <summary>
/// Gets or sets the visual style for the series.
/// </summary>
[Category("Style")]
[Description("Indicates the visual style for the series.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ChartSeriesVisualStyle ChartSeriesVisualStyle
{
get
{
if (_ChartSeriesVisualStyle == null)
{
_ChartSeriesVisualStyle = new ChartSeriesVisualStyle();
StyleVisualChangeHandler(null, _ChartSeriesVisualStyle);
}
return (_ChartSeriesVisualStyle);
}
set
{
if (_ChartSeriesVisualStyle != value)
{
ChartSeriesVisualStyle oldValue = _ChartSeriesVisualStyle;
_ChartSeriesVisualStyle = value;
OnStyleChanged("ChartSeriesVisualStyle", oldValue, value);
if (oldValue != null)
oldValue.Dispose();
}
}
}
#endregion
#region ConvexHullDisplayMode
/// <summary>
/// Gets or sets the ConvexHull display mode.
/// </summary>
[DefaultValue(ConvexHullDisplayMode.NotSet), Category("Display")]
[Description("Indicates the ConvexHull display mode.")]
[Editor("DevComponents.Charts.Design.FlagsEnumUIEditor, DevComponents.Charts.Design, " +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public ConvexHullDisplayMode ConvexHullDisplayMode
{
get { return (_ConvexHullDisplayMode); }
set
{
if (value != _ConvexHullDisplayMode)
{
_ConvexHullDisplayMode = value;
OnPropertyChangedEx("ConvexHullDisplayMode", VisualChangeType.Render);
}
}
}
#endregion
#region CrosshairEnabled
///<summary>
/// Gets or sets whether Crosshair support is enabled for the series.
///</summary>
[DefaultValue(Tbool.NotSet), Category("Crosshair")]
[Description("Indicates whether Crosshair support is enabled for the series.")]
public Tbool CrosshairEnabled
{
get { return (_CrosshairEnabled); }
set
{
if (value != _CrosshairEnabled)
{
_CrosshairEnabled = value;
OnPropertyChanged("CrosshairEnabled");
}
}
}
#endregion
#region CrosshairHighlightPoints
///<summary>
/// Gets or sets whether Crosshair Point highlighting is enabled for the series.
///</summary>
[DefaultValue(Tbool.NotSet), Category("Crosshair")]
[Description("Indicates whether Crosshair Point highlighting is enabled for the series.")]
public Tbool CrosshairHighlightPoints
{
get { return (_CrosshairHighlightPoints); }
set
{
if (value != _CrosshairHighlightPoints)
{
_CrosshairHighlightPoints = value;
OnPropertyChanged("CrosshairHighlightPoints");
}
}
}
#endregion
#region CrosshairShowLabels
///<summary>
/// Gets or sets whether Crosshair labels are shown for the series.
///</summary>
[DefaultValue(Tbool.NotSet), Category("Crosshair")]
[Description("Indicates whether Crosshair labels are shown for the series.")]
public Tbool CrosshairShowLabels
{
get { return (_CrosshairShowLabels); }
set
{
if (value != _CrosshairShowLabels)
{
_CrosshairShowLabels = value;
OnPropertyChanged("CrosshairShowLabels");
}
}
}
#endregion
#region DataLabels
///<summary>
/// Gets or sets the list of instance Data Labels.
///</summary>
[DefaultValue(null), Category("DataLabel")]
[Description("Indicates the list of instance Data Labels.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public DataLabelCollection DataLabels
{
get
{
if (_DataLabels == null)
{
_DataLabels = new DataLabelCollection();
_DataLabels.PropertyChanged += DataLabels_PropertyChanged;
_DataLabels.CollectionChanged += DataLabels_CollectionChanged;
}
return (_DataLabels);
}
internal set
{
if (_DataLabels != null)
{
_DataLabels.PropertyChanged -= DataLabels_PropertyChanged;
_DataLabels.CollectionChanged -= DataLabels_CollectionChanged;
}
_DataLabels = value;
if (_DataLabels != null)
{
_DataLabels.PropertyChanged += DataLabels_PropertyChanged;
_DataLabels.CollectionChanged += DataLabels_CollectionChanged;
}
}
}
#region DataLabels_PropertyChanged
void DataLabels_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
InvalidateRender();
}
#endregion
#region DataLabels_CollectionChanged
private void DataLabels_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (DataLabel dl in e.NewItems)
{
dl.Parent = this;
dl.PropertyChanged += DataLabel_PropertyChanged;
}
break;
case NotifyCollectionChangedAction.Replace:
foreach (DataLabel dl in e.OldItems)
{
dl.Parent = null;
dl.PropertyChanged -= DataLabel_PropertyChanged;
}
foreach (DataLabel dl in e.NewItems)
{
dl.Parent = this;
dl.PropertyChanged += DataLabel_PropertyChanged;
}
break;
case NotifyCollectionChangedAction.Remove:
case NotifyCollectionChangedAction.Reset:
if (e.OldItems != null)
{
foreach (DataLabel dl in e.OldItems)
dl.PropertyChanged -= DataLabel_PropertyChanged;
}
break;
}
InvalidateLayout();
}
private void DataLabel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
InvalidateLayout();
}
#endregion
#endregion
#region DataLabelVisualStyle
/// <summary>
/// Gets or sets the visual style for the data labels.
/// </summary>
[Category("Style")]
[Description("Indicates the visual style for the data labels.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public DataLabelVisualStyle DataLabelVisualStyle
{
get
{
if (_DataLabelVisualStyle == null)
{
_DataLabelVisualStyle = new DataLabelVisualStyle();
StyleVisualChangeHandler(null, _DataLabelVisualStyle);
}
return (_DataLabelVisualStyle);
}
set
{
if (_DataLabelVisualStyle != value)
{
DataLabelVisualStyle oldValue = _DataLabelVisualStyle;
_DataLabelVisualStyle = value;
OnStyleChanged("DataLabelVisualStyle", oldValue, value);
if (oldValue != null)
oldValue.Dispose();
}
}
}
#endregion
#region DataPropertyNameSeries
///<summary>
/// Gets or sets the name of the data field to which the Series Name is bound.
///</summary>
[DefaultValue(null), Category("Data")]
[Description("Indicates the name of the data field to which the Series Name is bound.")]
public string DataPropertyNameSeries
{
get { return (_DataPropertyNameSeries); }
set
{
if (value != _DataPropertyNameSeries)
{
_DataPropertyNameSeries = value;
if (NeedToUpdateBindings == false)
{
NeedToUpdateBindings = true;
InvalidateLayout();
}
OnPropertyChangedEx("DataPropertyNameSeries", VisualChangeType.Layout);
}
}
}
#endregion
#region DataPropertyNameX
///<summary>
/// Gets or sets the name of the data field to which the X-Axis data is bound.
///</summary>
[DefaultValue(null), Category("Data")]
[Description("Indicates the name of the data field to which the X-Axis data is bound.")]
public string DataPropertyNameX
{
get { return (_DataPropertyNameX); }
set
{
if (value != _DataPropertyNameX)
{
_DataPropertyNameX = value;
if (NeedToUpdateBindings == false)
{
NeedToUpdateBindings = true;
InvalidateLayout();
}
OnPropertyChangedEx("DataPropertyNameX", VisualChangeType.Layout);
}
}
}
#endregion
#region DataPropertyNamesY
///<summary>
/// Gets or sets the names of the data fields to which the Y-Axis data is bound.
///</summary>
[DefaultValue(null), Category("Data")]
[Description("Indicates the names of the data fields to which the Y-Axis data is bound.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public CustomCollection<string> DataPropertyNamesY
{
get
{
if (_DataPropertyNamesY == null)
{
_DataPropertyNamesY = new CustomCollection<string>();
_DataPropertyNamesY.CollectionChanged += DataPropertyNamesY_CollectionChanged;
}
return (_DataPropertyNamesY);
}
set
{
if (value != _DataPropertyNamesY)
{
if (_DataPropertyNamesY != null)
{
_DataPropertyNamesY.Clear();
_DataPropertyNamesY.CollectionChanged -= DataPropertyNamesY_CollectionChanged;
}
_DataPropertyNamesY = value;
if (_DataPropertyNamesY != null)
_DataPropertyNamesY.CollectionChanged += DataPropertyNamesY_CollectionChanged;
OnPropertyChangedEx("DataPropertyNamesY", Style.VisualChangeType.Layout);
}
}
}
void DataPropertyNamesY_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (NeedToUpdateBindings == false)
{
NeedToUpdateBindings = true;
InvalidateLayout();
}
}
#endregion
#region DataMember
///<summary>
/// Gets or sets the name of the list or table
/// in the data source that the Series is bound to.
///</summary>
[DefaultValue(null), Category("Data")]
[Description("Indicates the name of the list or table in the data source that the Series is bound to.")]
public string DataMember
{
get { return (_DataMember); }
set
{
if (_DataBinder != null)
_DataBinder.Clear();
_DataMember = value;
NeedToUpdateBindings = true;
OnPropertyChangedEx("DataMember", VisualChangeType.Layout);
}
}
#endregion
#region DataSource
///<summary>
/// Gets or sets the data source that the Series is bound to.
///</summary>
[DefaultValue(null), AttributeProvider(typeof(IListSource)), Category("Data")]
[Description("Indicates the data source that the Series is bound to.")]
public object DataSource
{
get { return (_DataSource); }
set
{
if (_DataBinder != null)
_DataBinder.Clear();
_DataSource = value;
NeedToUpdateBindings = true;
OnPropertyChangedEx("DataSource", VisualChangeType.Layout);
}
}
#endregion
#region DefaultPaletteColor
/// <summary>
/// Gets the default palette color assigned to the series when it
/// is added to the chart.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("Indicates the default palette color assigned to the series when it is added to the chart.")]
public Color DefaultPaletteColor
{
get { return (_DefaultPaletteColor); }
internal set
{
if (value != _DefaultPaletteColor)
{
_DefaultPaletteColor = value;
InvalidateStyle();
}
}
}
#endregion
#region DisplayLinePointsOnTop
/// <summary>
/// Gets or sets whether series points are displayed on top of series line.
/// </summary>
[DefaultValue(true), Category("Appearance")]
[Description("Indicates whether series points are displayed on top of series line.")]
public bool DisplayLinePointsOnTop
{
get { return (TestState(States.DisplayLinePointsOnTop)); }
set
{
if (value != DisplayLinePointsOnTop)
{
SetState(States.DisplayLinePointsOnTop, value);
OnPropertyChangedEx("DisplayLinePointsOnTop", VisualChangeType.Render);
}
}
}
#endregion
#region DotPlotIndexValue
/// <summary>
/// Gets or sets the value used to index between DotPlot points. Default is 1.
/// </summary>
[DefaultValue(1.0d), Category("Display")]
[Description("Indicates the value used to index between DotPlot points. Default is 1.")]
public double DotPlotIndexValue
{
get { return (_DotPlotIndexValue); }
set
{
if (value != _DotPlotIndexValue)
{
if (value < 0)
throw new ArgumentException("Value must be > 0");
_DotPlotIndexValue = value;
OnPropertyChangedEx("DotPlotIndexValue", VisualChangeType.Layout);
}
}
}
#endregion
#region EffectiveDataLabelStyle
/// <summary>
/// Gets a reference to the DataLabel effective (cached, composite) style.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DataLabelVisualStyle EffectiveDataLabelStyle
{
get { return (_EffectiveDataLabelStyle.Style); }
}
#endregion
#region EffectiveSeriesStyle
/// <summary>
/// Gets a reference to the Series's effective (cached, composite) style.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("Indicates a reference to the Series's Effective (cached, composite) style.")]
public ChartSeriesVisualStyle EffectiveChartSeriesStyle
{
get { return (_EffectiveChartSeriesStyle.Style); }
}
#endregion
#region EmptyValues
///<summary>
/// Gets or sets the value(s) used to determine if
/// a series point is empty or missing.
///</summary>
[Category("Empty")]
[Description("Indicates the value(s) used to determine if a series point is empty or missing.")]
[Editor("DevComponents.Charts.Design.SeriesPointValueEditor, DevComponents.Charts.Design, " +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public object[] EmptyValues
{
get { return (_EmptyValues); }
set
{
if (value != _EmptyValues)
{
_EmptyValues = value;
OnPropertyChangedEx("EmptyValue", Style.VisualChangeType.Layout);
}
}
}
#endregion
#region EnableEmptyValues
/// <summary>
/// Gets or sets whether EmptyValues are processed in the series
/// </summary>
[DefaultValue(false), Category("Empty")]
[Description("Indicates whether EmptyValues are processed in the series.")]
public bool EnableEmptyValues
{
get { return (TestState(States.EnableEmptyValues)); }
set
{
if (value != EnableEmptyValues)
{
SetState(States.EnableEmptyValues, value);
_PointData = null;
_EmptyPointData = null;
_StepPointData = null;
OnPropertyChangedEx("EnableEmptyValues", VisualChangeType.Layout);
}
}
}
#endregion
#region GroupId
///<summary>
/// Gets or sets the logical grouping Id used to group qualitative series.
///</summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int GroupId
{
get { return (_GroupId); }
set
{
if (value != _GroupId)
{
_GroupId = value;
OnPropertyChangedEx("GroupId", Style.VisualChangeType.Layout);
}
}
}
#endregion
#region HiLoBarType
///<summary>
/// Gets or sets the Series HiLoBar Type.
///</summary>
[DefaultValue(HiLoBarType.Box), Category("Appearance")]
[Description("Indicates the Series HiLoBar Type.")]
public HiLoBarType HiLoBarType
{
get { return (_HiLoBarType); }
set
{
if (value != _HiLoBarType)
{
_HiLoBarType = value;
OnPropertyChangedEx("HiLoBarType", VisualChangeType.Layout);
}
}
}
#endregion
#region IsDisplayed
///<summary>
/// Gets whether the series is displayed (based upon Visibility and Legend state).
///</summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool IsDisplayed
{
get
{
ChartXy chartXy = Parent as ChartXy;
ItemCheckAction ica = (chartXy != null)
? chartXy.Legend.ItemCheckAction : ItemCheckAction.ShowItem;
return ((Visible == true) &&
(ica == ItemCheckAction.None ||
(ShowCheckBoxInLegend == false || CheckedInLegend == true)));
}
}
#endregion
#region MaxValueX
///<summary>
/// Gets the series Maximum X value.
///</summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public object MaxValueX
{
get
{
UpdateSeriesRange();
if (IsRotated == true)
return (_MaxValueY);
return (_MaxValueX);
}
}
#endregion
#region MaxValueY
///<summary>
/// Gets the series Maximum Y value.
///</summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public object MaxValueY
{
get
{
UpdateSeriesRange();
if (IsRotated == true)
return (_MaxValueX);
return (_MaxValueY);
}
}
#endregion
#region MinValueX
///<summary>
/// Gets the series minimum X value.
///</summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public object MinValueX
{
get
{
UpdateSeriesRange();
if (IsRotated == true)
return (_MinValueY);
return (_MinValueX);
}
}
#endregion
#region MinValueY
///<summary>
/// Gets the series minimum Y value.
///</summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public object MinValueY
{
get
{
UpdateSeriesRange();
if (IsRotated == true)
return (_MinValueX);
return (_MinValueY);
}
}
#endregion
#region PointLabelDisplayMode
/// <summary>
/// Gets or sets the display mode for the chart PointLabels.
/// </summary>
[DefaultValue(PointLabelDisplayMode.NotSet), Category("DataLabel")]
[Description("Indicates the display mode for the chart PointLabels.")]
[Editor("DevComponents.Charts.Design.FlagsEnumUIEditor, DevComponents.Charts.Design, " +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public PointLabelDisplayMode PointLabelDisplayMode
{
get { return (_PointLabelDisplayMode); }
set
{
if (value != _PointLabelDisplayMode)
{
_PointLabelDisplayMode = value;
InvalidatePointLabels();
OnPropertyChangedEx("PointLabelDisplayMode", VisualChangeType.Render);
}
}
}
#endregion
#region PointLabelMinDistance
///<summary>
/// Gets or sets the minimum distance between label data points.
///</summary>
[DefaultValue(0), Category("DataLabel")]
[Description("Indicates the minimum distance between label data points.")]
public int PointLabelMinDistance
{
get { return (_PointLabelMinDistance); }
set
{
if (value != _PointLabelMinDistance)
{
if (value < 0)
throw new Exception("Minimum Distance must be >= 0");
_PointLabelMinDistance = value;
InvalidatePointLabels();
OnPropertyChangedEx("PointLabelMinDistance", Style.VisualChangeType.Render);
}
}
}
#endregion
#region PointLabelSkip
///<summary>
/// Gets or sets the number of inter-label points to skip.
///</summary>
[DefaultValue(0), Category("DataLabel")]
[Description("Indicates the number of inter-label points to skip.")]
public int PointLabelSkip
{
get { return (_PointLabelSkip); }
set
{
if (value != _PointLabelSkip)
{
if (value < 0)
throw new Exception("Skip value must be >= 0");
_PointLabelSkip = value;
InvalidatePointLabels();
OnPropertyChangedEx("PointLabelSkip", Style.VisualChangeType.Render);
}
}
}
#endregion
#region ScaleTypeX
///<summary>
/// Gets or sets the X axis Scale Type.
///</summary>
[DefaultValue(ScaleType.NotSet), Category("Axis")]
[Description("Indicates the X axis Scale Type.")]
public ScaleType ScaleTypeX
{
get { return (_ScaleTypeX); }
set
{
if (value != _ScaleTypeX)
{
if (ValidScaleTypeX(value) == false)
throw new Exception("Incompatible ScaleTypeX for defined series data.");
_ScaleTypeX = value;
InvalidatePoints();
OnPropertyChangedEx("ScaleTypeX", VisualChangeType.Layout);
}
}
}
#region ValidScaleTypeX
private bool ValidScaleTypeX(ScaleType scaleType)
{
if (scaleType == ScaleType.NotSet || scaleType == ScaleType.Auto)
return (true);
if (SeriesPoints.Count > 0)
{
for (int i = 0; i < SeriesPoints.Count; i++)
{
SeriesPoint sp = SeriesPoints[i];
if (sp.ValueX != null)
{
Type dataType = sp.ValueX.GetType();
ScaleType autoType = SeriesPoint.GetScaleType(dataType);
if (scaleType == autoType)
return (true);
if (scaleType == ScaleType.Qualitative)
return (true);
return (false);
}
}
}
return (true);
}
#endregion
#endregion
#region ScaleTypeY
///<summary>
/// Gets or sets the Y axis Scale Type.
///</summary>
[DefaultValue(ScaleType.NotSet), Category("Axis")]
[Description("Indicates the Y axis Scale Type.")]
public ScaleType ScaleTypeY
{
get { return (_ScaleTypeY); }
set
{
if (value != _ScaleTypeY)
{
if (ValidScaleTypeY(value) == false)
throw new Exception("Incompatible ScaleTypeY for defined series data.");
_ScaleTypeY = value;
InvalidatePoints();
OnPropertyChangedEx("ScaleTypeY", VisualChangeType.Layout);
}
}
}
#region ValidScaleTypeY
private bool ValidScaleTypeY(ScaleType scaleType)
{
if (scaleType == ScaleType.NotSet || scaleType == ScaleType.Auto)
return (true);
if (SeriesPoints.Count > 0)
{
for (int i = 0; i < SeriesPoints.Count; i++)
{
SeriesPoint sp = SeriesPoints[i];
if (sp.ValueY != null && sp.ValueY.Length > 0)
{
Type dataType = sp.ValueY[0].GetType();
ScaleType autoType = SeriesPoint.GetScaleType(dataType);
if (scaleType == autoType)
return (true);
if (scaleType == ScaleType.Qualitative)
return (true);
return (false);
}
}
}
return (true);
}
#endregion
#endregion
#region SeriesPoints
///<summary>
/// Gets the series point data collection
///</summary>
[Category("Data")]
[Description("Indicates the series point data collection.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public SeriesPointCollection SeriesPoints
{
get
{
if (_SeriesPoints == null)
{
_SeriesPoints = new SeriesPointCollection();
_SeriesPoints.CollectionChanged += SeriesPoints_CollectionChanged;
}
return (_SeriesPoints);
}
set
{
if (value != _SeriesPoints)
{
if (_SeriesPoints != null)
_SeriesPoints.CollectionChanged -= SeriesPoints_CollectionChanged;
_SeriesPoints = value;
if (_SeriesPoints != null)
_SeriesPoints.CollectionChanged += SeriesPoints_CollectionChanged;
}
}
}
#region SeriesPoints_CollectionChanged
void SeriesPoints_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
SeriesRangeChanged = true;
InvalidateLayout();
}
#endregion
#endregion
#region SeriesType
///<summary>
/// Gets or sets the Series Type.
///</summary>
[DefaultValue(SeriesType.Point), Category("Appearance")]
[Description("Indicates the Series Type.")]
public SeriesType SeriesType
{
get { return (_SeriesType); }
set
{
if (value != _SeriesType)
{
_SeriesType = value;
IsRotated = (
SeriesType == SeriesType.HorizontalDot ||
SeriesType == SeriesType.HorizontalBar ||
SeriesType == SeriesType.HorizontalHiLoBar);
BaseChart chart = Parent as BaseChart;
if (chart != null)
{
SeriesRangeChanged = true;
chart.SeriesRangeChanged = true;
}
OnPropertyChangedEx("SeriesType", VisualChangeType.Layout);
}
}
}
#endregion
#region ShowHiLoBarMedianLines
/// <summary>
/// Gets or sets whether defined HiLoBar Median lines are shown.
/// </summary>
[DefaultValue(false), Category("Empty")]
[Description("Indicates whether defined HiLoBar Median lines are shown.")]
public bool ShowHiLoBarMedianLines
{
get { return (TestState(States.ShowHiLoBarMedianLines)); }
set
{
if (value != ShowHiLoBarMedianLines)
{
SetState(States.ShowHiLoBarMedianLines, value);
OnPropertyChangedEx("ShowHiLoBarMedianLines", VisualChangeType.Render);
}
}
}
#endregion
#region ShowEmptyLines
/// <summary>
/// Gets or sets whether EmptyLines are shown in the series.
/// </summary>
[DefaultValue(false), Category("Empty")]
[Description("Indicates whether EmptyLines are shown in the series.")]
public bool ShowEmptyLines
{
get { return (TestState(States.ShowEmptyLines)); }
set
{
if (value != ShowEmptyLines)
{
SetState(States.ShowEmptyLines, value);
InvalidatePoints();
OnPropertyChangedEx("ShowEmptyLines", VisualChangeType.Render);
}
}
}
#endregion
#region ShowEmptyPoints
/// <summary>
/// Gets or sets whether EmptyPoints are shown in the series.
/// </summary>
[DefaultValue(false), Category("Empty")]
[Description("Indicates whether EmptyPoints are shown in the series.")]
public bool ShowEmptyPoints
{
get { return (TestState(States.ShowEmptyPoints)); }
set
{
if (value != ShowEmptyPoints)
{
SetState(States.ShowEmptyPoints, value);
InvalidatePoints();
OnPropertyChangedEx("ShowEmptyPoints", VisualChangeType.Render);
}
}
}
#endregion
#region ShowOriginValueLabels
/// <summary>
/// Gets or sets whether labels are shown for 'Origin' data values.
/// </summary>
[DefaultValue(true), Category("Appearance")]
[Description("Indicates whether labels are shown for 'Origin' data values.")]
public bool ShowOriginValueLabels
{
get { return (TestState(States.ShowOriginValueLabels)); }
set
{
if (value != ShowOriginValueLabels)
{
SetState(States.ShowOriginValueLabels, value);
OnPropertyChangedEx("ShowOriginValueLabels", VisualChangeType.Layout);
}
}
}
#endregion
#region StackQualitativePoints
/// <summary>
/// Gets or sets whether Qualitative points are
/// stacked or spread across the associated grouped column.
/// </summary>
[DefaultValue(true), Category("Appearance")]
[Description("Indicates whether Qualitative points are stacked or spread across the associated grouped column.")]
public bool StackQualitativePoints
{
get { return (TestState(States.StackQualitativePoints)); }
set
{
if (value != StackQualitativePoints)
{
SetState(States.StackQualitativePoints, value);
OnPropertyChangedEx("StackQualitativePoints", VisualChangeType.Layout);
}
}
}
#endregion
#region StepLines
/// <summary>
/// Gets or sets which 'Step lines' are displayed.
/// </summary>
[DefaultValue(StepLines.NotSet), Category("Display")]
[Description("Indicates which 'Step lines' are displayed.")]
public StepLines StepLines
{
get { return (_StepLines); }
set
{
if (value != _StepLines)
{
_StepLines = value;
OnPropertyChangedEx("StepLines", VisualChangeType.Render);
}
}
}
#endregion
#region StepLineMode
/// <summary>
/// Gets or sets the mode used to render "Step Lines" in
/// the defined Line series.
/// </summary>
[DefaultValue(StepLineMode.NotSet), Category("Display")]
[Description("Indicates the mode used to render 'Step Lines' in the defined Line series.")]
public StepLineMode StepLineMode
{
get { return (_StepLineMode); }
set
{
if (value != _StepLineMode)
{
_StepLineMode = value;
OnPropertyChangedEx("StepLineMode", VisualChangeType.Render);
}
}
}
#endregion
#endregion
#region Internal properties
#region BarOffset
internal int BarOffset
{
get { return (_BarOffset); }
set { _BarOffset = value; }
}
#endregion
#region BarShadingColors
internal Color[] BarShadingColors
{
get
{
if (_BarShadingColors == null)
{
// Top, Bottom, Left, Right
_BarShadingColors = new Color[] {
Color.FromArgb(200, Color.White),
Color.FromArgb(100, Color.Black),
Color.FromArgb(100, Color.Black),
Color.FromArgb(100, Color.Black)};
}
return (_BarShadingColors);
}
}
#endregion
#region BarWidth
internal int BarWidth
{
get { return (_BarWidth); }
set { _BarWidth = value; }
}
#endregion
#region DataBinder
internal DataBinder DataBinder
{
get
{
if (_DataBinder == null)
_DataBinder = new DataBinder(this);
return (_DataBinder);
}
set
{
if (_DataBinder != null)
_DataBinder.Clear();
_DataBinder = value;
}
}
#endregion
#region IsQualitativeXValues
internal bool IsQualitativeXValues
{
get
{
UpdateSeriesRange();
return (QualitativeXValues.Count > 0);
}
}
#endregion
#region IsQualitativeYValues
internal bool IsQualitativeYValues
{
get
{
UpdateSeriesRange();
return (QualitativeYValues.Count > 0);
}
}
#endregion
#region IsBarSeries
internal bool IsBarSeries
{
get
{
return (_SeriesType == SeriesType.HorizontalBar ||
_SeriesType == SeriesType.VerticalBar ||
_SeriesType == SeriesType.HorizontalHiLoBar ||
_SeriesType == SeriesType.VerticalHiLoBar);
}
}
#endregion
#region IsRotated
internal bool IsRotated
{
get { return (TestState(States.IsRotated)); }
set { SetState(States.IsRotated, value); }
}
#endregion
#region IsSorted
internal bool IsSorted
{
get { return (TestState(States.IsSorted)); }
set { SetState(States.IsSorted, value); }
}
#endregion
#region NeedToUpdateBindings
internal bool NeedToUpdateBindings
{
get { return (TestState(States.NeedToUpdateBindings)); }
set { SetState(States.NeedToUpdateBindings, value); }
}
#endregion
#region PlotData
internal object PlotData
{
get { return (_PlotData); }
set { _PlotData = value; }
}
#endregion
#region PointMarkerEmptyImage
internal Image PointMarkerEmptyImage
{
get { return (_PointMarkerEmptyImage); }
set { _PointMarkerEmptyImage = value; }
}
#endregion
#region PointMarkerImage
internal Image PointMarkerImage
{
get { return (_PointMarkerImage); }
set { _PointMarkerImage = value; }
}
#endregion
#region PointMarkerHighlightImage
internal Image PointMarkerHighlightImage
{
get { return (_PointMarkerHighlightImage); }
set { _PointMarkerHighlightImage = value; }
}
#endregion
#region PointOffset
internal Point PointOffset
{
get { return (_PointOffset); }
set { _PointOffset = value; }
}
#endregion
#region QualitativeXValues
internal List<object> QualitativeXValues
{
get
{
if (_QualitativeXValues == null)
_QualitativeXValues = new List<object>();
return (_QualitativeXValues);
}
set { _QualitativeXValues = value; }
}
#endregion
#region QualitativeYValues
internal List<object> QualitativeYValues
{
get
{
if (_QualitativeYValues == null)
_QualitativeYValues = new List<object>();
return (_QualitativeYValues);
}
set { _QualitativeYValues = value; }
}
#endregion
#region SeriesId
internal int SeriesId
{
get { return (_SeriesId); }
set { _SeriesId = value; }
}
#endregion
#region SeriesKey
internal object SeriesKey
{
get { return (_SeriesKey); }
set { _SeriesKey = value; }
}
#endregion
#region SeriesRangeChanged
internal bool SeriesRangeChanged
{
get { return (_SeriesRangeChanged); }
set
{
if (value != _SeriesRangeChanged)
{
_SeriesRangeChanged = value;
if (value == true)
{
BaseChart chart = Parent as BaseChart;
if (chart != null)
chart.SeriesRangeChanged = true;
_SortedSeriesPoints = null;
}
}
}
}
#endregion
#endregion
#region MeasureOverride
protected override void MeasureOverride(ChartLayoutInfo layoutInfo)
{
UpdateDataBindings();
UpdateMarkerImage(layoutInfo.Graphics);
}
#region UpdateDataBindings
internal void UpdateDataBindings()
{
if (NeedToUpdateBindings == true)
{
BaseChart chart = Parent as BaseChart;
object dataSource = DataSource ?? chart.DataSource;
string dataMember = (string.IsNullOrEmpty(DataMember) == false) ? DataMember : chart.DataMember;
if (dataSource != null)
{
SeriesPoints.Clear();
DataBinder dataBinder = DataBinder;
dataBinder.Clear();
dataBinder.DataConnect(dataSource, dataMember);
dataBinder.LoadSeriesData(this);
}
NeedToUpdateBindings = false;
}
}
#endregion
#region UpdateMarkerImage
private void UpdateMarkerImage(Graphics g)
{
switch (SeriesType)
{
case SeriesType.Bubble:
case SeriesType.VerticalDot:
case SeriesType.Line:
case SeriesType.Point:
case SeriesType.HorizontalDot:
if (PointMarkerImage == null)
{
ChartXy chartXy = Parent as ChartXy;
ChartSeriesVisualStyle sstyle = EffectiveChartSeriesStyle;
PointMarkerImage = chartXy.GetPointMarker(g, sstyle.MarkerVisualStyle);
}
break;
}
}
#endregion
#endregion
#region ArrangeOverride
protected override void ArrangeOverride(ChartLayoutInfo layoutInfo)
{
BoundsRelative = layoutInfo.LayoutBounds;
if (SeriesType == SeriesType.Bubble)
UpdateBubblePointOffset();
}
#region UpdateBubblePointOffset
private void UpdateBubblePointOffset()
{
BubblePlotData bdata = _PlotData as BubblePlotData;
if (bdata != null)
{
ChartXy chartXy = Parent as ChartXy;
Rectangle bounds = chartXy.ContentBoundsEx;
float minSize = Dpi.Width(BubbleMinSize);
float maxSize = (float)(Math.Min(bounds.Width, bounds.Height) * BubbleMaxPercentage);
double minTotalSize;
double maxTotalSize;
chartXy.GetChartBubbleData(out minTotalSize, out maxTotalSize);
BubbleSizeMode smode = GetBubbleSizeMode(chartXy);
double range = maxSize - minSize;
double sizeRange = (smode == BubbleSizeMode.Diameter)
? maxTotalSize - minTotalSize : AMath.ToScalar((float)(maxTotalSize - minTotalSize));
SortedSeriesPoints ssp = GetSortedSeriesPoints(chartXy);
for (int i = 0; i < ssp.Count; i++)
{
SeriesPoint sp = ssp[i];
if (sp.Visible == true)
{
int size = GetBubbleSize(sp, smode, minSize, maxSize, range, sizeRange);
sp.PointSize = new Size(size, size);
}
}
}
}
#region GetBubbleSize
private int GetBubbleSize(SeriesPoint sp,
BubbleSizeMode smode, double minSize, double maxSize, double range, double sizeRange)
{
if (sp.ValueY == null || sp.ValueY.Length < 2 || sizeRange == 0)
return (int)minSize;
double size = Math.Abs(GetDoubleValue(sp.ValueY[1]));
double value = (smode == BubbleSizeMode.Diameter)
? (size * range) / sizeRange
: (AMath.ToScalar((float)size) * range) / sizeRange;
if (BubbleScaleFactor > 0)
value *= BubbleScaleFactor;
value = Math.Max(minSize, value);
return ((int)Math.Min(maxSize, value));
}
#endregion
#endregion
#endregion
#region RenderOverride
protected override void RenderOverride(ChartRenderInfo renderInfo)
{
Graphics g = renderInfo.Graphics;
if (SeriesPoints.Count > 0)
{
ChartXy chartXy = Parent as ChartXy;
ChartSeriesVisualStyle sstyle = EffectiveChartSeriesStyle;
SortedSeriesPoints ssp = GetSortedSeriesPoints(chartXy);
ssp.SeriesLayoutCount = chartXy.SeriesLayoutCount;
UpdateMarkerImage(g);
int n = Dpi.Width1;
_RenderBounds = chartXy.ContentBounds;
_RenderBounds.Location = chartXy.GetGlobalAdjustedPoint(_RenderBounds.Location);
if (_RenderBounds.Width > 0 && _RenderBounds.Height > 0)
{
switch (SeriesType)
{
case SeriesType.Bubble:
RenderBubblePlot(g, chartXy, ssp, sstyle);
break;
case SeriesType.HorizontalBar:
RenderHBarPlot(g, chartXy, ssp, sstyle);
break;
case SeriesType.HorizontalDot:
RenderHDotPlot(g, chartXy, ssp, sstyle);
break;
case SeriesType.HorizontalHiLoBar:
RenderHStockPlot(renderInfo, chartXy, ssp, sstyle);
break;
case SeriesType.Point:
RenderPointPlot(g, chartXy, ssp, true, sstyle);
break;
case SeriesType.Line:
RenderLinePlot(g, chartXy, ssp, sstyle);
break;
case SeriesType.VerticalBar:
RenderVBarPlot(g, chartXy, ssp, sstyle);
break;
case SeriesType.VerticalDot:
RenderVDotPlot(g, chartXy, ssp, sstyle);
break;
case SeriesType.VerticalHiLoBar:
RenderVStockPlot(renderInfo, chartXy, ssp, sstyle);
break;
}
}
}
}
#region GetSortedSeriesPoints
internal SortedSeriesPoints GetSortedSeriesPoints(ChartXy chartXy)
{
if (_SortedSeriesPoints == null)
{
bool sort = (IsSorted == false && NeedSortedSeries(chartXy) == true);
_SortedSeriesPoints = new SortedSeriesPoints(this, sort);
if (SeriesType == SeriesType.VerticalDot || SeriesType == SeriesType.HorizontalDot)
CombineDuplicates(_SortedSeriesPoints);
}
return (_SortedSeriesPoints);
}
#region CombineDuplicates
private void CombineDuplicates(SortedSeriesPoints ssp)
{
SeriesPoint spLast = null;
List<int> cList = new List<int>();
List<int> iList = new List<int>();
int dcount = 0;
int spLastIndex = 0;
for (int i = 0; i < ssp.Count; i++)
{
SeriesPoint sp = ssp[i];
if (spLast != null && spLast.ValueX.Equals(sp.ValueX) == false)
{
iList.Add(spLastIndex);
cList.Add(dcount);
dcount = 0;
spLast = sp;
spLastIndex = (ssp.IndexArray != null ? ssp.IndexArray[i] : i);
}
dcount += GetDotCount(sp);
if (spLast == null)
{
spLast = sp;
spLastIndex = (ssp.IndexArray != null ? ssp.IndexArray[i] : i);
}
}
if (dcount > 0)
{
iList.Add(spLastIndex);
cList.Add(dcount);
}
int[] indexArray = new int[iList.Count];
int[] countArray = new int[iList.Count];
for (int i = 0; i < iList.Count; i++)
{
indexArray[i] = iList[i];
countArray[i] = cList[i];
}
ssp.IndexArray = indexArray;
ssp.CountArray = countArray;
}
#endregion
#region NeedSortedSeries
private bool NeedSortedSeries(ChartXy chartXy)
{
if (IsSorted == true || _ActualScaleTypeX == ScaleType.Qualitative)
return (false);
if (SeriesType != SeriesType.Line)
return (true);
ChartLineDisplayMode mode = GetLineDisplayMode(chartXy);
return ((mode & ChartLineDisplayMode.DisplayUnsorted) != ChartLineDisplayMode.DisplayUnsorted);
}
#endregion
#endregion
#region RenderBarPlot
#region RenderHBarPlot
private void RenderHBarPlot(Graphics g,
ChartXy chartXy, SortedSeriesPoints ssp, ChartSeriesVisualStyle sstyle)
{
g.RenderingOrigin = chartXy.GetLocalAdjustedPoint(Point.Empty);
BarRenderData rd = new BarRenderData(chartXy, AxisX ?? chartXy.AxisX);
rd.FillRange = GetBarFillRange(chartXy);
rd.BarShading = GetBarShading(chartXy);
rd.SeriesStyle = sstyle;
int index = 0;
bool isHistogram = false;
if (chartXy.BarShowAsHistogram == Tbool.True)
{
ChartAxis axisY = AxisY ?? chartXy.AxisY;
AxisBar axisBar = axisY.AxisBars[(int)AxisBarType.Bar];
if (axisBar.BarCount == 1)
{
TickmarkLayout layout = axisY.TickmarkLayout;
for (int i = 0; i < layout.Ticks.Length; i++)
{
if (layout.Ticks[i].LabelIndex >= 0)
{
index = i;
break;
}
}
isHistogram = true;
}
}
for (int i = 0; i < ssp.Count; i++)
{
SeriesPoint sp = ssp[i];
if (sp.Visible == true)
{
rd.Spt = sp.Point[0];
rd.Sp = sp;
RenderHBar(g, rd, isHistogram, i + index);
}
}
}
#region RenderHBar
private void RenderHBar(
Graphics g, BarRenderData rd, bool isHistogram, int index)
{
ChartXy chartXy = rd.ChartXy;
SeriesPoint sp = rd.Sp;
sp.PointSize = new Size(5, BarWidth);
Point ptt = chartXy.GetDataPointEx(this, sp, 0);
int y = (int)(ptt.Y + BarOffset - BarWidth / 2);
int height = BarWidth;
if (isHistogram == true)
y = GetHistogramSizeY(chartXy, ptt, index, out height);
int x1 = ptt.X;
int x2 = GetHBarStart(chartXy, sp);
int xOrigin = GetHBarOrigin(chartXy, rd.Axis, sp);
if (x1 > x2)
{
int xtemp = x1;
x1 = x2;
x2 = xtemp;
}
if (x2 <= xOrigin)
{
RenderLeftBar(g, rd, y, height, x1, x2, xOrigin);
}
else if (x1 >= xOrigin)
{
RenderRightBar(g, rd, y, height, x1, x2, xOrigin);
}
else
{
RenderLeftBar(g, rd, y, height, x1, xOrigin, xOrigin);
RenderRightBar(g, rd, y, height, xOrigin, x2, xOrigin);
}
}
#region GetHistogramSizeY
private int GetHistogramSizeY(
ChartXy chartXy, Point spt, int index, out int height)
{
ChartAxis axis = AxisY ?? chartXy.AxisY;
TickmarkLayout layout = axis.TickmarkLayout;
if (index < layout.Ticks.Length)
height = layout.Ticks[index + 1].TickPoint.Y - spt.Y;
else
height = (int)layout.MajorInterval;
int y = spt.Y - (int)(layout.MajorInterval / 2);
return (y);
}
#endregion
#region GetHBarStart
internal int GetHBarStart(ChartXy chartXy, SeriesPoint sp)
{
ChartAxis axis = AxisX ?? chartXy.AxisX;
object value = ((sp.ValueY.Length > 1)
? sp.ValueY[1] : chartXy.BarOrigin ?? null);
if (value == null)
{
if (axis.ScaleType == ScaleType.Quantitative)
value = 0;
else
value = axis.ActualMinValue;
}
return (chartXy.GetDataPointX(axis, value));
}
#endregion
#region GetHBarOrigin
private int GetHBarOrigin(
ChartXy chartXy, ChartAxis axis, SeriesPoint sp)
{
object value = ((sp.ValueY != null && sp.ValueY.Length > 2)
? sp.ValueY[2] : (chartXy.BarOrigin ?? null));
if (value == null)
{
if (axis.ScaleType == ScaleType.Quantitative)
value = 0;
else
value = axis.ActualMinValue;
}
return (chartXy.GetDataPointX(axis, value));
}
#endregion
#region RenderRightBar
private void RenderRightBar(Graphics g,
BarRenderData rd, int y, int height, int x1, int x2, int xOrigin)
{
Rectangle r = new Rectangle(x1, y, x2 - x1, Math.Max(1, height - 1));
if (r.IntersectsWith(_RenderBounds))
{
Background bk = rd.SeriesStyle.BarVisualStyle.Background;
ChartLineVisualStyle lstyle = rd.SeriesStyle.BarVisualStyle.Border;
// r is actual area, r2 is FillRange area
Rectangle r2 = r;
if (rd.FillRange == BarFillRange.BySeries)
{
r2.X = xOrigin;
r2.Width = rd.ChartXy.GetDataPointX(rd.Axis, MaxValueX) - r2.X;
}
BarSegment segment = (x1 > xOrigin) ? BarSegment.Right : BarSegment.RightPartial;
RenderFullHBar(g, rd, r, r2, bk, lstyle, segment);
}
}
#endregion
#region RenderLeftBar
private void RenderLeftBar(Graphics g,
BarRenderData rd, int y, int height, int x1, int x2, int xOrigin)
{
Rectangle r = new Rectangle(x1, y, x2 - x1, Math.Max(1, height - 1));
if (r.IntersectsWith(_RenderBounds))
{
ChartSeriesVisualStyle sstyle = rd.SeriesStyle;
Background bk = sstyle.BarVisualStyle.AlternateBackground;
if (bk.IsEmpty)
bk = sstyle.BarVisualStyle.Background;
ChartLineVisualStyle lstyle = sstyle.BarVisualStyle.AlternateBorder;
if (lstyle.IsEmpty)
lstyle = sstyle.BarVisualStyle.Border;
Rectangle r2 = r;
if (rd.FillRange == BarFillRange.BySeries)
{
int left = rd.ChartXy.GetDataPointX(rd.Axis, MinValueX);
r2.X = left;
r2.Width = xOrigin - left;
}
BarSegment segment = (x2 < xOrigin) ? BarSegment.Left : BarSegment.LeftPartial;
RenderFullHBar(g, rd, r, r2, bk, lstyle, segment);
}
}
#endregion
#region RenderFullHBar
private void RenderFullHBar(Graphics g, BarRenderData rd,
Rectangle r, Rectangle r2, Background bk, ChartLineVisualStyle lstyle, BarSegment segment)
{
if (r2.Width > 0 && r2.Height > 0)
{
ChartXy chartXy = rd.ChartXy;
ChartControl chartControl = ChartControl;
if (chartControl.DoPreRenderSeriesBarEvent(g, chartXy, this, rd.Sp, r, r2, segment) == false)
{
using (Brush br = bk.GetBrush(r2))
g.FillRectangle(br, r);
int lw = 0;
if (lstyle.LinePattern != LinePattern.None)
{
SmoothingMode sm = g.SmoothingMode;
g.SmoothingMode = SmoothingMode.None;
using (Pen pen = new Pen(lstyle.LineColor, Dpi.Width(lstyle.LineWidth)))
{
lw = (int)pen.Width;
if (lstyle.LinePattern != LinePattern.NotSet)
pen.DashStyle = (DashStyle)lstyle.LinePattern;
g.DrawRectangle(pen, r);
}
g.SmoothingMode = sm;
}
if (rd.BarShading == true)
{
Rectangle t = r;
t.Inflate(-lw/2, -lw/2);
t.Width++;
t.Height++;
RenderHBarShading(g, t, r2, segment);
}
chartControl.DoPostRenderSeriesBarEvent(g, chartXy, this, rd.Sp, r, r2, segment);
}
}
}
#region RenderHBarShading
private void RenderHBarShading(
Graphics g, Rectangle r, Rectangle r2, BarSegment segment)
{
if (r.Width > 6)
{
SmoothingMode sm = g.SmoothingMode;
g.SmoothingMode = SmoothingMode.None;
int n = (int)(r.Height *.15);
Color[] colors = (Color[])BarShadingColors.Clone();
colors[2] = Color.FromArgb(Math.Max(0,colors[2].A - 30), colors[2]);
colors[3] = Color.FromArgb(Math.Max(0, colors[3].A - 30), colors[3]);
Rectangle r3 = r;
r3.Inflate(1, 1);
using (LinearGradientBrush lbr = new LinearGradientBrush(r3, Color.Empty, Color.Empty, 90f))
{
lbr.WrapMode = WrapMode.Tile;
ColorBlend cb = new ColorBlend(4);
cb.Colors = new Color[] { colors[0], Color.Transparent, Color.Transparent, colors[1] };
cb.Positions = new float[] { 0f, .25f, .75f, 1f };
lbr.InterpolationColors = cb;
r3.Inflate(-1, -1);
g.FillRectangle(lbr, r3);
}
switch (segment)
{
case BarSegment.LeftPartial:
FillLeft(g, r, n, colors);
break;
case BarSegment.RightPartial:
FillRight(g, r, n, colors);
break;
default:
FillLeft(g, r, n, colors);
FillRight(g, r, n, colors);
break;
}
g.SmoothingMode = sm;
}
}
#region FillLeft
private void FillLeft(Graphics g, Rectangle r, int n, Color[] colors)
{
r.Width = n - 1;
r.Inflate(1, 0);
using (LinearGradientBrush lbr = new LinearGradientBrush(r, colors[2], Color.Transparent, 0f))
{
lbr.WrapMode = WrapMode.TileFlipX;
r.X++;
g.FillRectangle(lbr, r);
}
}
#endregion
#region FillRight
private void FillRight(Graphics g, Rectangle r, int n, Color[] colors)
{
r.X = r.Right - n;
r.Width = n;
r.Inflate(1, 0);
using (LinearGradientBrush lbr = new LinearGradientBrush(r, colors[2], Color.Transparent, 180f))
{
r.X++;
r.Width--;
g.FillRectangle(lbr, r);
}
}
#endregion
#endregion
#endregion
#endregion
#endregion
#region RenderVBarPlot
private void RenderVBarPlot(Graphics g,
ChartXy chartXy, SortedSeriesPoints ssp, ChartSeriesVisualStyle sstyle)
{
PointData pd = GatherSeriesPoints(chartXy, ssp, 0, ssp.Count, false);
if (pd.Points.Count > 0)
{
g.RenderingOrigin = chartXy.GetLocalAdjustedPoint(Point.Empty);
BarRenderData rd = new BarRenderData(chartXy, AxisY ?? chartXy.AxisY);
rd.FillRange = GetBarFillRange(chartXy);
rd.BarShading = GetBarShading(chartXy);
rd.SeriesStyle = sstyle;
int index = 0;
bool isHistogram = false;
if (chartXy.BarShowAsHistogram == Tbool.True)
{
ChartAxis axisX = AxisX ?? chartXy.AxisX;
AxisBar axisBar = axisX.AxisBars[(int)AxisBarType.Bar];
if (axisBar.BarCount == 1)
{
TickmarkLayout layout = axisX.TickmarkLayout;
for (int i = 0; i < layout.Ticks.Length; i++)
{
if (layout.Ticks[i].LabelIndex >= 0)
{
index = i;
break;
}
}
isHistogram = true;
}
}
for (int i = 0; i < pd.Points.Count; i++)
{
Point[] pts = pd.Points[i];
SeriesPoint[] spts = pd.SeriesPoints[i];
for (int j = 0; j < pts.Length; j++)
{
rd.Spt = pts[j];
rd.Sp = spts[j];
RenderVBar(g, rd, isHistogram, j + index);
}
}
}
}
#region RenderVBar
private void RenderVBar(
Graphics g, BarRenderData rd, bool isHistogram, int index)
{
ChartXy chartXy = rd.ChartXy;
SeriesPoint sp = rd.Sp;
Point spt = rd.Spt;
sp.PointSize = new Size(BarWidth, 5);
int x = (int)(spt.X + BarOffset - BarWidth / 2);
int width = BarWidth;
if (isHistogram == true)
x = GetHistogramSizeX(chartXy, spt, index, out width);
int y1 = spt.Y;
int y2 = GetVBarStart(chartXy, sp);
int yOrigin = GetVBarOrigin(chartXy, rd.Axis, sp);
if (y1 > y2)
{
int ytemp = y1;
y1 = y2;
y2 = ytemp;
}
if (y2 <= yOrigin)
{
RenderAscendingBar(g, rd, x, width, y1, y2, yOrigin);
}
else if (y1 >= yOrigin)
{
RenderDescendingBar(g, rd, x, width, y1, y2, yOrigin);
}
else
{
RenderAscendingBar(g, rd, x, width, y1, yOrigin, yOrigin);
RenderDescendingBar(g, rd, x, width, yOrigin, y2, yOrigin);
}
}
#region GetHistogramSizeX
private int GetHistogramSizeX(
ChartXy chartXy, Point spt, int index, out int width)
{
ChartAxis axis = AxisX ?? chartXy.AxisX;
TickmarkLayout layout = axis.TickmarkLayout;
if (index < layout.Ticks.Length)
width = layout.Ticks[index + 1].TickPoint.X - spt.X;
else
width = (int)layout.MajorInterval;
int x = spt.X - (int)(layout.MajorInterval / 2);
return (x);
}
#endregion
#region GetVBarStart
internal int GetVBarStart(ChartXy chartXy, SeriesPoint sp)
{
ChartAxis axis = AxisY ?? chartXy.AxisY;
object value = ((sp.ValueY != null && sp.ValueY.Length > 1)
? sp.ValueY[1] : (chartXy.BarOrigin ?? null));
if (value == null)
{
if (axis.ScaleType == ScaleType.Quantitative)
value = 0;
else
value = axis.ActualMinValue;
}
return (chartXy.GetDataPointY(axis, value));
}
#endregion
#region GetVBarOrigin
private int GetVBarOrigin(
ChartXy chartXy, ChartAxis axis, SeriesPoint sp)
{
object value = ((sp.ValueY != null && sp.ValueY.Length > 2)
? sp.ValueY[2] : (chartXy.BarOrigin ?? null));
if (value == null)
{
if (axis.ScaleType == ScaleType.Quantitative)
value = 0;
else
value = axis.ActualMinValue;
}
return (chartXy.GetDataPointY(axis, value));
}
#endregion
#region RenderAscendingBar
private void RenderAscendingBar(Graphics g,
BarRenderData rd, int x, int width, int y1, int y2, int yOrigin)
{
Rectangle r = new Rectangle(x, y1, Math.Max(1, width - 1), y2 - y1);
if (r.IntersectsWith(_RenderBounds))
{
Background bk = rd.SeriesStyle.BarVisualStyle.Background;
ChartLineVisualStyle lstyle = rd.SeriesStyle.BarVisualStyle.Border;
Rectangle r2 = r;
if (rd.FillRange == BarFillRange.BySeries)
{
int top = rd.ChartXy.GetDataPointY(rd.Axis, MaxValueY);
r2.Y = top;
r2.Height = yOrigin - top;
}
BarSegment segment = (y2 < yOrigin) ? BarSegment.Top : BarSegment.TopPartial;
RenderFullVBar(g, rd, r, r2, bk, lstyle, segment);
}
}
#endregion
#region RenderDescendingBar
private void RenderDescendingBar(Graphics g,
BarRenderData rd, int x, int width, int y1, int y2, int yOrigin)
{
Rectangle r = new Rectangle(x, y1, Math.Max(1, width - 1), y2 - y1);
if (r.IntersectsWith(_RenderBounds))
{
ChartSeriesVisualStyle sstyle = rd.SeriesStyle;
Background bk = sstyle.BarVisualStyle.AlternateBackground;
if (bk.IsEmpty)
bk = sstyle.BarVisualStyle.Background;
ChartLineVisualStyle lstyle = sstyle.BarVisualStyle.AlternateBorder;
if (lstyle.IsEmpty)
lstyle = sstyle.BarVisualStyle.Border;
Rectangle r2 = r;
if (GetBarFillRange(rd.ChartXy) == BarFillRange.BySeries)
{
r2.Y = yOrigin;
r2.Height = rd.ChartXy.GetDataPointY(rd.Axis, MinValueY) - r2.Y;
}
BarSegment segment = (y1 > yOrigin) ? BarSegment.Bottom : BarSegment.BottomPartial;
RenderFullVBar(g, rd, r, r2, bk, lstyle, segment);
}
}
#endregion
#region RenderFullVBar
private void RenderFullVBar(Graphics g, BarRenderData rd,
Rectangle r, Rectangle r2, Background bk, ChartLineVisualStyle lstyle, BarSegment segment)
{
if (r2.Width > 0 && r2.Height > 0)
{
ChartXy chartXy = rd.ChartXy;
ChartControl chartControl = ChartControl;
if (chartControl.DoPreRenderSeriesBarEvent(g, chartXy, this, rd.Sp, r, r2, segment) == false)
{
using (Brush br = bk.GetBrush(r2))
g.FillRectangle(br, r);
int lw = 0;
if (lstyle.LinePattern != LinePattern.None)
{
SmoothingMode sm = g.SmoothingMode;
g.SmoothingMode = SmoothingMode.None;
using (Pen pen = new Pen(lstyle.LineColor, Dpi.Width(lstyle.LineWidth)))
{
lw = (int)pen.Width;
if (lstyle.LinePattern != LinePattern.NotSet)
pen.DashStyle = (DashStyle)lstyle.LinePattern;
g.DrawRectangle(pen, r);
}
g.SmoothingMode = sm;
}
if (rd.BarShading == true)
{
Rectangle t = r;
t.Inflate(-lw/2, -lw/2);
t.Width++;
t.Height++;
RenderVBarShading(g, t, r2, segment);
}
chartControl.DoPostRenderSeriesBarEvent(g, chartXy, this, rd.Sp, r, r2, segment);
}
}
}
#region RenderVBarShading
private void RenderVBarShading(
Graphics g, Rectangle r, Rectangle r2, BarSegment segment)
{
int n = r.Width / 10 + 1;
if (r.Width > 6 && r.Height > n)
{
SmoothingMode sm = g.SmoothingMode;
g.SmoothingMode = SmoothingMode.None;
Color[] colors = (Color[])BarShadingColors.Clone();
Rectangle r3 = r;
using (LinearGradientBrush lbr = new LinearGradientBrush(r3, Color.Empty, Color.Empty, 0f))
{
lbr.WrapMode = WrapMode.TileFlipX;
ColorBlend cb = new ColorBlend(4);
cb.Colors = new Color[] { colors[2], Color.Transparent, Color.Transparent, colors[3] };
cb.Positions = new float[] { 0f, .15f, .85f, 1f };
lbr.InterpolationColors = cb;
g.FillRectangle(lbr, r3);
}
switch (segment)
{
case BarSegment.TopPartial:
FillTop(g, r, n, colors);
break;
case BarSegment.BottomPartial:
FillBottom(g, r, n, colors);
break;
default:
FillTop(g, r, n, colors);
FillBottom(g, r, n, colors);
break;
}
g.SmoothingMode = sm;
}
}
#region FillTop
private void FillTop(Graphics g, Rectangle r, int n, Color[] colors)
{
using (Pen pen = new Pen(colors[0]))
{
Point pt1 = new Point(r.X + 1, r.Y);
Point pt2 = new Point(r.Right - 2, r.Y);
for (int i = 0; i < n; i++)
{
g.DrawLine(pen, pt1, pt2);
pt1.X++;
pt2.X--;
pt1.Y++;
pt2.Y++;
}
}
}
#endregion
#region FillBottom
private void FillBottom(Graphics g, Rectangle r, int n, Color[] colors)
{
using (Pen pen = new Pen(colors[1]))
{
Point pt1 = new Point(r.X + 1, r.Bottom - 1);
Point pt2 = new Point(r.Right - 2, r.Bottom - 1);
for (int i = 0; i < n; i++)
{
g.DrawLine(pen, pt1, pt2);
pt1.X++;
pt2.X--;
pt1.Y--;
pt2.Y--;
}
}
}
#endregion
#endregion
#endregion
#endregion
#endregion
#region GetBarFillRange
private BarFillRange GetBarFillRange(ChartXy chartXy)
{
BarFillRange fillRange = BarFillRange;
if (fillRange == BarFillRange.NotSet)
fillRange = chartXy.BarFillRange;
return ((fillRange != BarFillRange.NotSet)
? fillRange : BarFillRange.ByBar);
}
#endregion
#region GetBarLabelPosition
internal BarLabelPosition GetBarLabelPosition(ChartXy chartXy)
{
BarLabelPosition labelPos = BarLabelPosition;
if (labelPos == BarLabelPosition.NotSet)
labelPos = chartXy.BarLabelPosition;
return ((labelPos != BarLabelPosition.NotSet)
? labelPos : BarLabelPosition.Center);
}
#endregion
#region GetBarShading
private bool GetBarShading(ChartXy chartXy)
{
Tbool barShading = BarShadingEnabled;
if (barShading == Tbool.NotSet)
barShading = chartXy.BarShadingEnabled;
return (barShading == Tbool.True);
}
#endregion
#endregion
#region RenderBubblePlot
private void RenderBubblePlot(Graphics g,
ChartXy chartXy, SortedSeriesPoints ssp, ChartSeriesVisualStyle sstyle)
{
BubblePlotData bdata = _PlotData as BubblePlotData;
if (bdata != null)
{
double minIntensity = 32;
double maxIntensity = 255;
PointMarkerVisualStyle pstyle = sstyle.MarkerVisualStyle;
PointMarkerVisualStyle hstyle = GetHighlightStyle(chartXy, sstyle);
if (DisplayLinePointsOnTop == true)
RenderConvexHull(g, chartXy, ssp, sstyle, pstyle);
BubbleIntensityMode imode = GetBubbleIntensityMode(chartXy);
for (int i = 0; i < ssp.Count; i++)
{
SeriesPoint sp = ssp[i];
if (sp.Visible == true)
{
int size = sp.PointSize.Width;
Point pt = chartXy.GetDataPointNa(this, sp, 0);
Rectangle r = new Rectangle(pt.X - size / 2, pt.Y - size / 2, size, size);
if (r.IntersectsWith(_RenderBounds))
{
Point ppt = chartXy.GetLocalAdjustedPoint(pt);
bool isCrossPoint = chartXy.IsCrosshairSeriesPoint(this, ppt);
int intensity = GetIntensity(sp, imode, bdata, minIntensity, maxIntensity);
PointMarkerVisualStyle style = (hstyle != null && isCrossPoint) ? hstyle : pstyle;
Image image = style.GetPointMarkerImage();
if (image == null)
image = GetPointMarker(g, style, r.Size);
if (image != null)
{
g.DrawImage(image, r);
}
else if (style.Type == PointMarkerType.Ellipse || style.Type == PointMarkerType.NotSet)
{
using (Brush br = style.Background.GetBrush(r, intensity))
{
g.FillEllipse(br, r);
if (style.BorderColor.IsEmpty == false && style.BorderWidth > 0)
{
using (Pen pen = new Pen(style.BorderColor, Dpi.Width(style.BorderWidth)))
g.DrawEllipse(pen, r);
}
}
}
}
}
}
if (DisplayLinePointsOnTop == false)
RenderConvexHull(g, chartXy, ssp, sstyle, pstyle);
if (hstyle != null)
hstyle.Dispose();
}
}
#region GetIntensity
private int GetIntensity(SeriesPoint sp,
BubbleIntensityMode imode, BubblePlotData bdata, double minIntensity, double maxIntensity)
{
if (imode != BubbleIntensityMode.None && imode != BubbleIntensityMode.NotSet)
{
if (sp.ValueY.Length > 2)
{
double intensity = -1;
if (sp.ValueY[2] is double)
intensity = (double)sp.ValueY[2];
else if (sp.ValueY[2] is int)
intensity = Convert.ToDouble(sp.ValueY[2]);
if (imode == BubbleIntensityMode.Alpha)
return ((int)intensity);
if (intensity >= 0)
{
double range = maxIntensity - minIntensity;
double intensityRange = bdata.MaxIntensity - bdata.MinIntensity;
if (intensityRange <= 0)
return (-1);
return (int)(((intensity - bdata.MinIntensity) * range) / intensityRange + minIntensity);
}
}
}
return (-1);
}
#endregion
#region GetBubbleSizeMode
private BubbleSizeMode GetBubbleSizeMode(ChartXy chartXy)
{
if (BubbleSizeMode != BubbleSizeMode.NotSet)
return (BubbleSizeMode);
if (chartXy.BubbleSizeMode != BubbleSizeMode.NotSet)
return (chartXy.BubbleSizeMode);
return (BubbleSizeMode.Area);
}
#endregion
#region GetBubbleIntensityMode
private BubbleIntensityMode GetBubbleIntensityMode(ChartXy chartXy)
{
if (BubbleIntensityMode != BubbleIntensityMode.NotSet)
return (BubbleIntensityMode);
if (chartXy.BubbleIntensityMode != BubbleIntensityMode.NotSet)
return (chartXy.BubbleIntensityMode);
return (BubbleIntensityMode.None);
}
#endregion
#region GetPointMarker
internal Image GetPointMarker(Graphics g, PointMarkerVisualStyle style, Size size)
{
if (style.Type == PointMarkerType.NotSet ||
style.Type == PointMarkerType.None || style.Type == PointMarkerType.Ellipse)
{
return (null);
}
if (_PointMarker == null)
_PointMarker = new PointMarker();
return (_PointMarker.GetMarkerBitmap(g, style.Type, style.PointCount,
size, style.Rotation, style.Background, style.BorderColor, style.BorderWidth));
}
#endregion
#endregion
#region RenderDotPlot
#region RenderHDotPlot
private void RenderHDotPlot(Graphics g,
ChartXy chartXy, SortedSeriesPoints ssp, ChartSeriesVisualStyle sstyle)
{
Image marker = PointMarkerImage;
if (marker != null)
{
Size maxSize = chartXy.GetMaxDotPlotMarkerSize();
for (int i = 0; i < ssp.Count; i++)
{
SeriesPoint sp = ssp[i];
if (sp.Visible == true)
{
object pointValueX = chartXy.GetDataPointValueX(this, sp);
Point pt = chartXy.GetPointFromValue(this, 0, pointValueX);
Point ppt = new Point(pt.X + maxSize.Width / 2, pt.Y);
int dcount = ssp.CountArray[i];
for (int j = 0; j < dcount; j++)
{
RenderPointMarker(g, chartXy, sp, ppt, maxSize, marker);
ppt.X += maxSize.Width;
}
}
}
}
}
#endregion
#region RenderVDotPlot
private void RenderVDotPlot(Graphics g,
ChartXy chartXy, SortedSeriesPoints ssp, ChartSeriesVisualStyle sstyle)
{
Image marker = PointMarkerImage;
if (marker != null)
{
Size maxSize = chartXy.GetMaxDotPlotMarkerSize();
for (int i = 0; i < ssp.Count; i++)
{
SeriesPoint sp = ssp[i];
if (sp.Visible == true)
{
Point pt = chartXy.GetDataPointNa(this, sp, -1);
Point ppt = new Point(pt.X, pt.Y - maxSize.Height / 2);
int dcount = ssp.CountArray[i];
for (int j = 0; j < dcount; j++)
{
RenderPointMarker(g, chartXy, sp, ppt, maxSize, marker);
ppt.Y -= maxSize.Height;
}
}
}
}
}
#endregion
#region GetDotCount
private int GetDotCount(SeriesPoint sp)
{
if (sp.ValueY != null && sp.ValueY.Length > 0)
{
int count = 0;
foreach (object o in sp.ValueY)
{
if (o is int)
count += (int)o;
else if (o is double)
count += (int)Convert.ChangeType(o, typeof(int));
}
return (count);
}
return (1);
}
#endregion
#endregion
#region RenderPointPlot
private void RenderPointPlot(Graphics g, ChartXy chartXy,
SortedSeriesPoints ssp, bool showHull, ChartSeriesVisualStyle sstyle)
{
PointData pd = GatherSeriesPoints(chartXy, ssp, 0, ssp.Count, true);
if (pd.Points.Count > 0)
{
PointMarkerVisualStyle pstyle = sstyle.MarkerVisualStyle;
PointMarkerVisualStyle hstyle = GetHighlightStyle(chartXy, sstyle);
if (showHull == true)
RenderConvexHull(g, chartXy, ssp, sstyle, pstyle);
if (hstyle == null)
{
Image marker = chartXy.GetPointMarker(g, pstyle);
if (marker != null)
{
for (int i=0; i<pd.Points.Count; i++)
{
Point[] pts = pd.Points[i];
SeriesPoint[] spts = pd.SeriesPoints[i];
for (int j = 0; j < pts.Length; j++)
RenderPointMarker(g, chartXy, spts[j], pts[j], Size.Empty, marker);
}
}
}
else
{
for (int i = 0; i < pd.Points.Count; i++)
{
Point[] pts = pd.Points[i];
SeriesPoint[] spts = pd.SeriesPoints[i];
for (int j = 0; j < pts.Length; j++)
{
Point ppt = pts[j];
Point ppt2 = chartXy.GetLocalAdjustedPoint(ppt);
Image marker = (chartXy.IsCrosshairSeriesPoint(this, ppt2))
? GetHighlightImage(g, chartXy, hstyle) : PointMarkerImage;
RenderPointMarker(g, chartXy, spts[j], ppt, Size.Empty, marker);
}
}
}
if (ShowEmptyPoints == true)
RenderEmptyPoints(g, chartXy, pd, sstyle);
}
}
#region RenderPointMarker
private void RenderPointMarker(Graphics g,
ChartXy chartXy, SeriesPoint sp, Point pt, Size maxSize, Image marker)
{
if (marker != null)
{
ChartControl control = ChartControl;
Image ptMarker = marker;
Size markerSize = marker.Size;
Size size = maxSize.IsEmpty ? markerSize : maxSize;
sp.PointSize = size;
Point ptc = new Point(
pt.X - markerSize.Width / 2,
pt.Y - markerSize.Height / 2);
Rectangle r = new Rectangle(ptc, markerSize);
if (r.IntersectsWith(_RenderBounds))
{
if (control.DoPreRenderSeriesPointEvent(g,
chartXy, this, sp, pt, size, ref ptMarker) == false)
{
if (ptMarker != null)
{
g.DrawImageUnscaled(ptMarker, ptc);
control.DoPostRenderSeriesPointEvent(g,
chartXy, this, sp, pt, ptMarker.Size, ptMarker);
}
}
}
}
}
#endregion
#region RenderConvexHull
private void RenderConvexHull(Graphics g, ChartXy chartXy,
SortedSeriesPoints ssp, ChartSeriesVisualStyle sstyle, PointMarkerVisualStyle pstyle)
{
ConvexHullDisplayMode mode = GetConvexHullDisplayMode(chartXy);
if (mode != ConvexHullDisplayMode.None)
{
if (_ConvexHullPoints == null)
{
PointData pd = GatherSeriesPointsEx(chartXy, ssp, 0, ssp.Count, true);
_ConvexHullPoints = ConvexHull.GetConvexHull(
(pd.Points.Count == 1) ? pd.Points[0] : CombineListPoints(pd.Points));
}
if (_ConvexHullPoints.Length > 3)
{
using (GraphicsPath path = new GraphicsPath())
{
path.AddPolygon(_ConvexHullPoints);
if ((mode & ConvexHullDisplayMode.DisplayBackground) == ConvexHullDisplayMode.DisplayBackground)
{
Rectangle r = Rectangle.Round(path.GetBounds());
Background bg = (sstyle.ConvexHullBackground.IsEmpty)
? pstyle.Background : sstyle.ConvexHullBackground;
using (Brush br = bg.GetBrush(r))
g.FillPath(br, path);
}
if ((mode & ConvexHullDisplayMode.DisplayBorder) == ConvexHullDisplayMode.DisplayBorder)
{
Color color;
int width;
LinePattern pattern;
if (sstyle.ConvexHullLineStyle.IsEmpty == false)
{
color = sstyle.ConvexHullLineStyle.LineColor;
width = sstyle.ConvexHullLineStyle.LineWidth;
pattern = sstyle.ConvexHullLineStyle.LinePattern;
}
else
{
color = pstyle.BorderColor;
width = pstyle.BorderWidth;
pattern = LinePattern.Solid;
}
if (pattern != LinePattern.None)
{
using (Pen pen = new Pen(color, Dpi.Width(width)))
{
if (pattern != LinePattern.NotSet)
pen.DashStyle = (DashStyle)pattern;
g.DrawPath(pen, path);
}
}
}
}
}
}
}
#region GetConvexHullDisplayMode
private ConvexHullDisplayMode GetConvexHullDisplayMode(ChartXy chartXy)
{
if (ConvexHullDisplayMode != ConvexHullDisplayMode.NotSet)
return (ConvexHullDisplayMode);
ConvexHullDisplayMode mode = chartXy.ConvexHullDisplayMode;
if (mode != ConvexHullDisplayMode.NotSet)
return (mode);
return (ConvexHullDisplayMode.None);
}
#endregion
#region CombineListPoints
private Point[] CombineListPoints(List<Point[]> plist)
{
int n = 0;
foreach (Point[] points in plist)
n += points.Length;
Point[] fpoints = new Point[n];
n = 0;
foreach (Point[] points in plist)
{
for (int i = 0; i < points.Length; i++)
fpoints[n++] = points[i];
}
return (fpoints);
}
#endregion
#endregion
#region RenderEmptyPoints
private void RenderEmptyPoints(Graphics g,
ChartXy chartXy, PointData pd, ChartSeriesVisualStyle sstyle)
{
PointData epd = _EmptyPointData;
if (epd != null && epd.Points.Count > 0)
{
PointMarkerVisualStyle pstyle = sstyle.MarkerEmptyVisualStyle;
Image marker = GetEmptyMarkerImage(g, chartXy, pstyle);
if (marker != null)
{
for (int i = 0; i < epd.Points.Count; i++)
{
Point[] epts = epd.Points[i];
SeriesPoint[] septs = epd.SeriesPoints[i];
Point[] pts = GetEmptyPointRange(epts[0]);
int run = pts[0].X - pts[1].X;
int rise = pts[0].Y - pts[1].Y;
double slope = (run != 0) ? (double)rise / run : 0;
double b = pts[0].Y - (slope * pts[0].X);
for (int j = 0; j < epts.Length; j++)
{
Point ept = epts[j];
SeriesPoint sept = septs[j];
Point ppt = new Point(ept.X, (int)(slope * ept.X + b));
RenderPointMarker(g, chartXy, sept, ppt, Size.Empty, marker);
}
}
}
}
}
#region GetEmptyPointRange
private Point[] GetEmptyPointRange(Point pt)
{
Point[] pts = new Point[2];
pts[0] = Point.Empty;
pts[1] = Point.Empty;
PointData pd = _PointData;
for (int i = 0; i < pd.Points.Count; i++)
{
Point[] lps = pd.Points[i];
if (pt.X <= lps[0].X)
{
pts[1] = lps[0];
if (i == 0)
pts[0] = pts[1];
return (pts);
}
pts[0] = lps[lps.Length - 1];
}
pts[1] = pts[0];
return (pts);
}
#endregion
#endregion
#endregion
#region RenderLinePlot
private void RenderLinePlot(Graphics g,
ChartXy chartXy, SortedSeriesPoints ssp, ChartSeriesVisualStyle sstyle)
{
PointData pd = GatherSeriesPoints(chartXy, ssp, 0, ssp.Count, false);
if (pd.Points.Count > 0)
{
ChartLineDisplayMode lineMode = GetLineDisplayMode(chartXy);
ChartLineAreaDisplayMode areaMode = GetAreaDisplayMode(chartXy);
PointMarkerVisualStyle pstyle = sstyle.MarkerVisualStyle;
RenderConvexHull(g, chartXy, ssp, sstyle, pstyle);
if (DisplayLinePointsOnTop == true)
RenderLinePlotLines(g, chartXy, pd, lineMode, areaMode, sstyle);
if ((lineMode & ChartLineDisplayMode.DisplayPoints) == ChartLineDisplayMode.DisplayPoints)
{
RenderPointPlot(g, chartXy, ssp, false, sstyle);
}
else
{
if (ShowEmptyPoints == true)
RenderEmptyPoints(g, chartXy, pd, sstyle);
RenderPointLabelPoints(g, chartXy, sstyle);
if (HighLightPoints(chartXy) == true)
RenderHighlightPoints(g, chartXy, pd, sstyle);
}
if (DisplayLinePointsOnTop == false)
RenderLinePlotLines(g, chartXy, pd, lineMode, areaMode, sstyle);
}
}
#region RenderPointLabelPoints
private void RenderPointLabelPoints(Graphics g,
ChartXy chartXy, ChartSeriesVisualStyle sstyle)
{
List<PointLabelGroup> pointLabels = chartXy.PointLabels;
if (pointLabels != null && pointLabels.Count > 0)
{
foreach (PointLabelGroup lg in pointLabels)
{
if (lg.ChartSeries == this)
{
PointMarkerVisualStyle pstyle = sstyle.MarkerVisualStyle;
Image marker = chartXy.GetPointMarker(g, pstyle);
if (marker != null)
{
Size size = marker.Size;
for (int i = 0; i < lg.PointLabels.Count; i++)
{
PointLabel pl = lg.PointLabels[i];
if (pl.Visible == true && pl.SeriesPoint.IsEmpty == false)
{
DataLabelVisualStyle dstyle = GetPointLabelVisualStyle(pl);
if (dstyle.DrawPointMarker != Tbool.False)
{
SeriesPoint spt = pl.SeriesPoint;
Point ppt = pl.Point;
Point ppc = new Point(ppt.X, ppt.Y);
RenderPointMarker(g, chartXy, spt, ppc, Size.Empty, marker);
}
}
}
}
break;
}
}
}
}
#endregion
#region RenderLinePlotLines
private void RenderLinePlotLines(Graphics g, ChartXy chartXy, PointData pd,
ChartLineDisplayMode lineMode, ChartLineAreaDisplayMode areaMode, ChartSeriesVisualStyle sstyle)
{
if ((lineMode & ChartLineDisplayMode.DisplayStepLine) == ChartLineDisplayMode.DisplayStepLine)
{
StepLineMode slm = GetStepLineMode(chartXy);
if (slm != StepLineMode.None)
RenderStepLines(g, chartXy, pd, slm, areaMode, sstyle);
}
if ((lineMode & ChartLineDisplayMode.DisplayLine) == ChartLineDisplayMode.DisplayLine)
RenderLines(g, chartXy, pd, lineMode, areaMode, sstyle);
if ((lineMode & ChartLineDisplayMode.DisplaySpline) == ChartLineDisplayMode.DisplaySpline)
RenderSplines(g, chartXy, pd, lineMode, areaMode, sstyle);
if (ShowEmptyLines == true)
{
if ((lineMode & (ChartLineDisplayMode.DisplayLine | ChartLineDisplayMode.DisplaySpline)) != 0)
RenderEmptyLines(g, chartXy, pd.Points, areaMode, sstyle);
}
}
#region GetStepLineMode
private StepLineMode GetStepLineMode(ChartXy chartXy)
{
StepLineMode mode = StepLineMode;
if (mode == StepLineMode.NotSet)
mode = chartXy.StepLineMode;
if (mode == StepLineMode.NotSet)
mode = StepLineMode.HorizontalThenVertical;
return (mode);
}
#endregion
#region RenderLines
private void RenderLines(Graphics g, ChartXy chartXy,
PointData pd, ChartLineDisplayMode lineMode, ChartLineAreaDisplayMode areaMode, ChartSeriesVisualStyle sstyle)
{
ChartLineVisualStyle lstyle = sstyle.LineStyle;
if (lstyle.LinePattern != LinePattern.None)
{
using (Pen pen = new Pen(lstyle.LineColor, Dpi.Width(lstyle.LineWidth)))
{
if (lstyle.LinePattern != LinePattern.NotSet)
pen.DashStyle = (DashStyle)lstyle.LinePattern;
if ((lineMode & ChartLineDisplayMode.DisplayClosed) == ChartLineDisplayMode.DisplayClosed)
{
foreach (Point[] points in pd.Points)
{
if (points.Length > 1)
g.DrawLines(pen, points);
}
Point fp = pd.Points[0][0];
Point[] lps = pd.Points[pd.Points.Count - 1];
Point lp = lps[lps.Length - 1];
if (fp.Equals(lp) == false)
g.DrawLine(pen, lp, fp);
}
else
{
foreach (Point[] points in pd.Points)
{
if (points.Length > 1)
{
using (GraphicsPath path = new GraphicsPath())
{
path.AddLines(points);
if ((areaMode & ChartLineAreaDisplayMode.DisplayLine) == ChartLineAreaDisplayMode.DisplayLine)
RenderAreaBackground(g, chartXy, points, path, sstyle.LineAreaBackground);
g.DrawPath(pen, path);
}
}
}
}
}
}
}
#endregion
#region RenderSplines
private void RenderSplines(Graphics g, ChartXy chartXy, PointData pd,
ChartLineDisplayMode lineMode, ChartLineAreaDisplayMode areaMode, ChartSeriesVisualStyle sstyle)
{
ChartLineVisualStyle lstyle = sstyle.SplineStyle;
if (lstyle.LinePattern != LinePattern.None)
{
using (Pen pen = new Pen(lstyle.LineColor, Dpi.Width(lstyle.LineWidth)))
{
if (lstyle.LinePattern != LinePattern.NotSet)
pen.DashStyle = (DashStyle)lstyle.LinePattern;
if ((pd.Points.Count == 1) &&
(lineMode & ChartLineDisplayMode.DisplayClosed) == ChartLineDisplayMode.DisplayClosed)
{
Point[] points = pd.Points[0];
if (points.Length > 1)
g.DrawClosedCurve(pen, points);
}
else
{
foreach (Point[] points in pd.Points)
{
if (points.Length > 1)
{
using (GraphicsPath path = new GraphicsPath())
{
path.AddCurve(points);
if ((areaMode & ChartLineAreaDisplayMode.DisplaySpline) == ChartLineAreaDisplayMode.DisplaySpline)
RenderAreaBackground(g, chartXy, points, path, sstyle.SplineAreaBackground);
g.DrawPath(pen, path);
}
}
}
}
}
}
}
#endregion
#region RenderStepLines
private void RenderStepLines(Graphics g, ChartXy chartXy, PointData pd,
StepLineMode slm, ChartLineAreaDisplayMode areaMode, ChartSeriesVisualStyle sstyle)
{
StepLines sls = GetStepLines(chartXy);
if (sls != StepLines.None)
{
PointData sd = GetStepPointData(chartXy, pd, slm);
if (sd != null)
{
SmoothingMode sm = g.SmoothingMode;
g.SmoothingMode = SmoothingMode.Default;
ChartCapLineVisualStyle lstyle = sstyle.StepLineStyle;
if (sls == StepLines.Both)
{
RenderStepLinesEx1(g, sd, lstyle);
}
else
{
int n = ((sls == StepLines.Horizontal && (slm == StepLineMode.HorizontalThenVertical || slm == StepLineMode.MidPoint)) ||
(sls == StepLines.Vertical && slm == StepLineMode.VerticalThenHorizontal)) ? 0 : 1;
RenderStepLinesEx2(g, sd, n, lstyle);
if (sstyle.StepLineAltStyle.IsEmpty == false)
RenderStepLinesEx2(g, sd, n ^ 1, sstyle.StepLineAltStyle);
}
g.SmoothingMode = sm;
if ((areaMode & ChartLineAreaDisplayMode.DisplayStepLine) == ChartLineAreaDisplayMode.DisplayStepLine)
{
foreach (Point[] points in sd.Points)
{
using (GraphicsPath path = new GraphicsPath())
{
path.AddLines(points);
RenderAreaBackground(g, chartXy, points, path, sstyle.StepLineAreaBackground);
}
}
}
}
}
}
#region GetStepLines
private StepLines GetStepLines(ChartXy chartXy)
{
StepLines mode = StepLines;
if (mode == StepLines.NotSet)
mode = chartXy.StepLines;
if (mode == StepLines.NotSet)
mode = StepLines.Both;
return (mode);
}
#endregion
#region GetStepPointData
private PointData GetStepPointData(
ChartXy chartXy, PointData pd, Charts.StepLineMode slm)
{
if (_LastStepLineMode != slm)
_StepPointData = null;
if (_StepPointData == null)
{
PointData sd = new PointData();
sd.Points = new List<Point[]>();
foreach (Point[] points in pd.Points)
{
if (points.Length > 1)
sd.Points.Add(GetStepPoints(slm, points));
}
_StepPointData = sd;
_LastStepLineMode = slm;
}
return (_StepPointData);
}
#region GetStepPoints
private Point[] GetStepPoints(StepLineMode slm, Point[] pts)
{
if (slm == StepLineMode.HorizontalThenVertical || slm == StepLineMode.VerticalThenHorizontal)
{
Point[] points = new Point[pts.Length * 2 - 1];
if (slm == StepLineMode.HorizontalThenVertical)
{
for (int i = 0; i < pts.Length; i++)
{
int n = i * 2;
points[n] = pts[i];
if (i + 1 < pts.Length)
points[n + 1] = new Point(pts[i + 1].X, pts[i].Y);
}
}
else
{
for (int i = 0; i < pts.Length; i++)
{
int n = i * 2;
points[n] = pts[i];
if (i + 1 < pts.Length)
points[n + 1] = new Point(pts[i].X, pts[i + 1].Y);
}
}
return (points);
}
else
{
Point[] points = new Point[pts.Length * 2];
points[0] = pts[0];
for (int i = 0; i < pts.Length - 1; i++)
{
int n0 = i * 2 + 1;
int n1 = n0 + 1;
points[n0] = new Point((pts[i].X + pts[i + 1].X) / 2, pts[i].Y);
points[n1] = new Point(points[n0].X, pts[i + 1].Y);
}
points[points.Length - 1] = pts[pts.Length - 1];
return (points);
}
}
#endregion
#endregion
#region RenderStepLinesEx1
private void RenderStepLinesEx1(Graphics g, PointData sd, ChartCapLineVisualStyle lstyle)
{
if (lstyle.LinePattern != LinePattern.None)
{
using (Pen pen = new Pen(lstyle.LineColor, Dpi.Width(lstyle.LineWidth)))
{
if (lstyle.LinePattern != LinePattern.NotSet)
pen.DashStyle = (DashStyle)lstyle.LinePattern;
if (lstyle.StartCap != ChartLineCap.NotSet)
pen.StartCap = (LineCap)lstyle.StartCap;
if (lstyle.EndCap != ChartLineCap.NotSet)
pen.EndCap = (LineCap)lstyle.EndCap;
foreach (Point[] points in sd.Points)
{
if (points.Length > 1)
g.DrawLines(pen, points);
}
}
}
}
#endregion
#region RenderStepLinesEx2
private void RenderStepLinesEx2(Graphics g,
PointData sd, int n, ChartCapLineVisualStyle lstyle)
{
if (lstyle.LinePattern != LinePattern.None)
{
using (Pen pen = new Pen(lstyle.LineColor, Dpi.Width(lstyle.LineWidth)))
{
if (lstyle.LinePattern != LinePattern.NotSet)
pen.DashStyle = (DashStyle)lstyle.LinePattern;
if (lstyle.StartCap != ChartLineCap.NotSet)
pen.StartCap = (LineCap)lstyle.StartCap;
if (lstyle.EndCap != ChartLineCap.NotSet)
pen.EndCap = (LineCap)lstyle.EndCap;
foreach (Point[] points in sd.Points)
{
if (points.Length > 1)
{
for (int i = n; i < points.Length - 1; i += 2)
{
Point pt1 = points[i];
Point pt2 = points[i + 1];
g.DrawLine(pen, pt1, pt2);
}
}
}
}
}
}
#endregion
#endregion
#region RenderEmptyLines
private void RenderEmptyLines(Graphics g, ChartXy chartXy,
List<Point[]> lpoints, ChartLineAreaDisplayMode areaMode, ChartSeriesVisualStyle sstyle)
{
if (lpoints.Count > 1)
{
ChartLineVisualStyle lstyle = sstyle.EmptyStyle;
if (lstyle.LinePattern != LinePattern.None)
{
Point[] points = new Point[(lpoints.Count - 1) * 2];
Point[][] epoints = new Point[lpoints.Count - 1][];
for (int i = 0; i < lpoints.Count - 1; i++)
{
Point[] pts1 = lpoints[i];
Point[] pts2 = lpoints[i + 1];
epoints[i] = new Point[2];
epoints[i][0] = pts1[pts1.Length - 1];
epoints[i][1] = pts2[0];
}
for (int i = 0; i < points.Length / 2; i++ )
{
using (GraphicsPath path = new GraphicsPath())
{
path.AddLines(epoints[i]);
if ((areaMode & ChartLineAreaDisplayMode.DisplayEmptyLine) == ChartLineAreaDisplayMode.DisplayEmptyLine)
RenderAreaBackground(g, chartXy, epoints[i], path, sstyle.EmptyAreaBackground);
using (Pen pen = new Pen(lstyle.LineColor, Dpi.Width(lstyle.LineWidth)))
{
if (lstyle.LinePattern != LinePattern.NotSet)
pen.DashStyle = (DashStyle)lstyle.LinePattern;
g.DrawPath(pen, path);
}
}
}
}
}
}
#endregion
#region RenderAreaBackground
private void RenderAreaBackground(Graphics g,
ChartXy chartXy, Point[] points, GraphicsPath path, Background background)
{
bool backEmpty = (background == null || background.IsEmpty == true);
if (backEmpty == true)
background = new Background(Color.FromArgb(100, DefaultPaletteColor));
if (background != null && background.IsEmpty == false)
{
int y = chartXy.ContentBoundsEx.Bottom;
if (AreaBaseValue != null)
{
ChartAxis axis = _AxisY ?? chartXy.AxisY;
y = chartXy.GetDataPointY(axis, AreaBaseValue);
}
using (GraphicsPath path2 = new GraphicsPath())
{
path2.AddLine(new Point(points[0].X, y), points[0]);
path2.AddPath(path, true);
path2.AddLine(points[points.Length - 1], new Point(points[points.Length - 1].X, y));
path2.CloseFigure();
Rectangle r = Rectangle.Round(path2.GetBounds());
using (Brush br = background.GetBrush(r))
g.FillPath(br, path2);
}
}
if (backEmpty == true)
background.Dispose();
}
#endregion
#endregion
#region RenderHighlightPoints
private void RenderHighlightPoints(Graphics g,
ChartXy chartXy, PointData pd, ChartSeriesVisualStyle sstyle)
{
PointMarkerVisualStyle hstyle = GetHighlightStyle(chartXy, sstyle);
Image marker = GetHighlightImage(g, chartXy, hstyle);
if (marker != null)
{
Size size = marker.Size;
Point pt = chartXy.GetLocalAdjustedPoint(Point.Empty);
for (int i=0; i<pd.Points.Count; i++)
{
Point[] pts = pd.Points[i];
SeriesPoint[] spts = pd.SeriesPoints[i];
for (int j=0; j<pts.Length; j++)
{
Point ppt = pts[j];
Point ppc = new Point(ppt.X, ppt.Y);
Point lppc = new Point(ppt.X + pt.X, ppt.Y + pt.Y);
if (chartXy.IsCrosshairSeriesPoint(this, lppc) == true)
RenderPointMarker(g, chartXy, spts[j], ppc, Size.Empty, marker);
}
}
}
}
#endregion
#region GetLineDisplayMode
private ChartLineDisplayMode GetLineDisplayMode(ChartXy chartXy)
{
ChartLineDisplayMode mode = ChartLineDisplayMode;
if (mode == ChartLineDisplayMode.NotSet)
mode = chartXy.ChartLineDisplayMode;
if (mode == ChartLineDisplayMode.NotSet)
mode = ChartLineDisplayMode.DisplayLine;
return (mode);
}
#endregion
#region GetAreaDisplayMode
private ChartLineAreaDisplayMode GetAreaDisplayMode(ChartXy chartXy)
{
ChartLineAreaDisplayMode mode = ChartLineAreaDisplayMode;
if (mode == ChartLineAreaDisplayMode.NotSet)
mode = chartXy.ChartLineAreaDisplayMode;
if (mode == ChartLineAreaDisplayMode.NotSet)
mode = ChartLineAreaDisplayMode.None;
return (mode);
}
#endregion
#endregion
#region RenderStockPlot
#region RenderHStockPlot
private void RenderHStockPlot(ChartRenderInfo renderInfo,
ChartXy chartXy, SortedSeriesPoints ssp, ChartSeriesVisualStyle sstyle)
{
HiLoRenderData rd = new HiLoRenderData(chartXy, AxisX ?? chartXy.AxisX);
rd.SeriesStyle = sstyle;
for (int i = 0; i < ssp.Count; i++)
{
SeriesPoint sp = ssp[i];
if (sp.Visible == true)
{
rd.Sp = sp;
rd.Spt = sp.Point[0];
rd.Index = i;
RenderHStock(renderInfo, rd);
}
}
}
#region RenderHStock
private void RenderHStock(ChartRenderInfo renderInfo, HiLoRenderData rd)
{
Graphics g = renderInfo.Graphics;
rd.Value = GetHStockValues(rd.ChartXy, rd.Sp);
if (rd.Value[StockHigh] != int.MinValue)
{
Point pt = rd.ChartXy.GetDataPointEx(this, rd.Sp, 0);
Rectangle r = GetHBoundingRect(rd, pt);
if (r.IntersectsWith(_RenderBounds) == true)
{
int y = pt.Y + BarOffset;
rd.Sp.PointSize = new Size(5, BarWidth / 3);
switch (HiLoBarType)
{
case HiLoBarType.Box:
case HiLoBarType.Candle:
RenderHStockBox(g, rd, y);
break;
default:
RenderHStockHiLo(g, rd, y);
break;
}
}
}
}
#region GetHBoundingRect
private Rectangle GetHBoundingRect(HiLoRenderData rd, Point pt)
{
int x1 = rd.Value[StockHigh];
int x2 = rd.Value[StockLow];
if (rd.Value[StockOpen] != int.MinValue)
{
if (rd.Value[StockOpen] > x1)
x1 = rd.Value[StockOpen];
if (rd.Value[StockOpen] < x2)
x2 = rd.Value[StockOpen];
}
if (rd.Value[StockClose] != int.MinValue)
{
if (rd.Value[StockClose] > x1)
x1 = rd.Value[StockClose];
if (rd.Value[StockClose] < x2)
x2 = rd.Value[StockClose];
}
int y = pt.Y + BarOffset - BarWidth / 2;
return (new Rectangle(x2, y, x1 - x2, BarWidth));
}
#endregion
#region RenderHStockBox
private void RenderHStockBox(Graphics g, HiLoRenderData rd, int y)
{
int x1 = rd.Value[StockClose];
int x2 = rd.Value[StockOpen];
if (rd.Value[StockOpen] != int.MinValue && rd.Value[StockClose] != int.MinValue)
{
if (rd.Value[StockOpen] < rd.Value[StockClose])
{
x1 = rd.Value[StockOpen];
x2 = rd.Value[StockClose];
}
if (rd.Value[StockLow] > x1)
rd.Value[StockLow] = x1;
if (rd.Value[StockHigh] < x2)
rd.Value[StockHigh] = x2;
rd.IsAlternate = (rd.Value[StockOpen] > rd.Value[StockClose]);
RenderHStockBoxWhisker(g, rd,
rd.Value[StockLow], x1, y, HiLoBarSegment.LowWhisker);
RenderHStockBoxWhisker(g, rd,
x2, rd.Value[StockHigh], y, HiLoBarSegment.HighWhisker);
RenderHStockBoxOpenClose(g, rd, x1, x2, y);
}
else
{
int x = (x1 != int.MinValue) ? x1 : x2;
if (x != int.MinValue)
{
if (x > rd.Value[StockHigh])
rd.Value[StockHigh] = x;
if (x < rd.Value[StockLow])
rd.Value[StockLow] = x;
}
if (x < rd.Value[StockHigh] && x > rd.Value[StockLow])
{
RenderHStockBoxWhisker(g, rd, x, rd.Value[StockHigh], y, HiLoBarSegment.HighWhisker);
RenderHStockBoxWhisker(g, rd, rd.Value[StockLow], x, y, HiLoBarSegment.LowWhisker);
RenderHStockBoxOpenClose(g, rd, x, x, y);
}
else
{
RenderHStockBoxWhisker(g, rd,
rd.Value[StockLow], rd.Value[StockHigh], y, HiLoBarSegment.CenterLine);
if (x != int.MinValue)
RenderHStockBoxOpenClose(g, rd, x, x, y);
}
}
}
#region RenderHStockBoxWhisker
private void RenderHStockBoxWhisker(Graphics g,
HiLoRenderData rd, int x1, int x2, int y, HiLoBarSegment segment)
{
if (x2 > x1)
{
Point pt1 = new Point(x1, y);
Point pt2 = new Point(x2 + 1, y);
RenderBoxWhisker(g, rd, pt1, pt2, segment);
}
}
#endregion
#region RenderHStockBoxOpenClose
private void RenderHStockBoxOpenClose(
Graphics g, HiLoRenderData rd, int x1, int x2, int y)
{
if (x2 == x1)
{
x1--;
x2++;
}
x2++;
Point pt1 = new Point(x1, y - BarWidth / 2);
Point pt2 = new Point(x2, pt1.Y + BarWidth);
int lw = RenderStockBox(g, rd, pt1, pt2);
Rectangle r = new Rectangle(pt1.X, pt1.Y, pt2.X - pt1.X, pt2.Y - pt1.Y);
if (r.Width > 0 && r.Height > 0)
{
if (GetBarShading(rd.ChartXy) == true)
{
ChartControl chartControl = ChartControl;
if (chartControl.DoPreRenderSeriesHiloBarEvent(
g, rd.ChartXy, this, rd, pt1, pt2, HiLoBarSegment.BarShading) == false)
{
RenderHBarShading(g, r, r, BarSegment.Left);
chartControl.DoPostRenderSeriesHiLoBarEvent(
g, rd.ChartXy, this, rd, pt1, pt2, HiLoBarSegment.BarShading);
}
}
}
}
#endregion
#endregion
#region RenderHStockBoxMedian
private void RenderHStockBoxMedian(
Graphics g, HiLoRenderData rd, int y, int x1, int x2)
{
if (rd.Value.Length > StockMedian)
{
int x3 = rd.Value[StockMedian];
if (x3 > x1 && x3 < x2)
{
Point pt1 = new Point(x3, y);
Point pt2 = new Point(x3, y + BarWidth - 1);
ChartControl chartControl = ChartControl;
if (chartControl.DoPreRenderSeriesHiloBarEvent(
g, rd.ChartXy, this, rd, pt1, pt2, HiLoBarSegment.MedianLine) == false)
{
ChartLineVisualStyle lstyle = GetSegLineStyle(rd, HiLoBarSegment.MedianLine);
if (lstyle.LinePattern != LinePattern.None)
{
using (Pen pen = new Pen(lstyle.LineColor, Dpi.Width(lstyle.LineWidth)))
{
if (lstyle.LinePattern != LinePattern.NotSet)
pen.DashStyle = (DashStyle)lstyle.LinePattern;
if (lstyle.LineWidth > 1)
pt2.Y++;
g.DrawLine(pen, pt1, pt2);
}
}
chartControl.DoPostRenderSeriesHiLoBarEvent(
g, rd.ChartXy, this, rd, pt1, pt2, HiLoBarSegment.MedianLine);
}
}
}
}
#endregion
#region RenderHStockHiLo
private void RenderHStockHiLo(Graphics g, HiLoRenderData rd, int y)
{
int x1, x2, x3, x4;
NormalizeHiLoValues(rd, out x1, out x2, out x3, out x4);
ChartLineVisualStyle ostyle, cstyle;
NormalizeHiLoStyles(rd, out ostyle, out cstyle);
if (rd.Value[StockOpen] != int.MinValue)
{
Point pt1 = new Point(x2, y - BarWidth / 2);
Point pt2 = new Point(pt1.X, pt1.Y + BarWidth / 2);
RenderHiLoWhisker(g, rd, pt1, pt2, ostyle, HiLoBarSegment.OpenWhisker);
}
if (rd.Value[StockClose] != int.MinValue)
{
Point pt1 = new Point(x3, y);
Point pt2 = new Point(pt1.X, pt1.Y + BarWidth / 2 + 1);
RenderHiLoWhisker(g, rd, pt1, pt2, cstyle, HiLoBarSegment.CloseWhisker);
}
if (rd.IsAlternate == false)
{
int x = x2;
x2 = x3;
x3 = x;
ChartLineVisualStyle style = ostyle;
ostyle = cstyle;
cstyle = ostyle;
}
if ((rd.IsAlternate == false && _RenderFullDefRange == true) ||
(rd.IsAlternate == true && _RenderFullAltRange == true))
{
RenderHiLoRange(g, rd,
new Point(x1, y), new Point(x4, y), HiLoBarSegment.FullRange);
}
else
{
// Open value either not specified or is
// set to High value.
if (x1 == x2 && x3 != x4)
x2 = x3;
if (x2 < x1)
{
int n = (ostyle != null) ? (ostyle.LineWidth + 1) / 2 : 1;
RenderHiLoRange(g, rd,
new Point(x1, y), new Point(x2 + n, y), HiLoBarSegment.HighWhisker);
}
if (x3 > x4)
{
int n = 1;
// Low segment extends to the top.
if (x3 == x1)
n = (cstyle.LineWidth + 1) / 2;
// We have a Center segment.
else if (x3 != x2)
n = -cstyle.LineWidth / 2;
RenderHiLoRange(g, rd,
new Point(x3 + n, y), new Point(x4, y), HiLoBarSegment.LowWhisker);
}
if (x2 > x3 || (x1 == x2 && x3 == x4))
{
ChartLineVisualStyle y2Style = (x2 == rd.Value[StockOpen]) ? ostyle : cstyle;
ChartLineVisualStyle y3Style = (x3 == rd.Value[StockOpen]) ? ostyle : cstyle;
if (y2Style != null)
x2 += ((y2Style.LineWidth + 1) / 2 );
if (y3Style != null)
x3 -= (y3Style.LineWidth / 2);
RenderHiLoRange(g, rd,
new Point(x2, y), new Point(x3, y), HiLoBarSegment.CenterLine);
}
}
}
#endregion
#endregion
#endregion
#region RenderVStockPlot
private void RenderVStockPlot(ChartRenderInfo renderInfo,
ChartXy chartXy, SortedSeriesPoints ssp, ChartSeriesVisualStyle sstyle)
{
HiLoRenderData rd = new HiLoRenderData(chartXy, AxisY ?? chartXy.AxisY);
rd.SeriesStyle = sstyle;
for (int i = 0; i < ssp.Count; i++)
{
SeriesPoint sp = ssp[i];
if (sp.Visible == true)
{
if (sp.ValueY.Length > 0)
{
rd.Sp = sp;
rd.Spt = sp.Point[0];
rd.Index = i;
rd.IsAlternate = false;
RenderVStock(renderInfo, rd);
}
}
}
}
#region RenderVStock
private void RenderVStock(ChartRenderInfo renderInfo, HiLoRenderData rd)
{
Graphics g = renderInfo.Graphics;
rd.Value = GetVStockValues(rd.ChartXy, rd.Sp);
if (rd.Value[StockHigh] != int.MinValue)
{
Point pt = rd.ChartXy.GetDataPointEx(this, rd.Sp, 0);
Rectangle r = GetVBoundingRect(rd, pt);
if (r.IntersectsWith(_RenderBounds) == true)
{
int x = pt.X + BarOffset;
rd.Sp.PointSize = new Size(BarWidth/3, 5);
switch (HiLoBarType)
{
case HiLoBarType.Box:
case HiLoBarType.Candle:
RenderVStockBox(g, rd, x);
break;
default:
RenderVStockHiLo(g, rd, x);
break;
}
}
}
}
#region GetVBoundingRect
private Rectangle GetVBoundingRect(HiLoRenderData rd, Point pt)
{
int y1 = rd.Value[StockHigh];
int y2 = rd.Value[StockLow];
if (rd.Value[StockOpen] != int.MinValue)
{
if (y1 > rd.Value[StockOpen])
y1 = rd.Value[StockOpen];
if (y2 < rd.Value[StockOpen])
y2 = rd.Value[StockOpen];
}
if (rd.Value[StockClose] != int.MinValue)
{
if (y1 > rd.Value[StockClose])
y1 = rd.Value[StockClose];
if (y2 < rd.Value[StockClose])
y2 = rd.Value[StockClose];
}
int x = pt.X + BarOffset - BarWidth / 2;
return (new Rectangle(x, y1, BarWidth, y2 - y1));
}
#endregion
#region RenderVStockBox
private void RenderVStockBox(Graphics g, HiLoRenderData rd, int x)
{
int y1 = rd.Value[StockOpen];
int y2 = rd.Value[StockClose];
if (rd.Value[StockOpen] != int.MinValue && rd.Value[StockClose] != int.MinValue)
{
if (rd.Value[StockOpen] > rd.Value[StockClose])
{
y1 = rd.Value[StockClose];
y2 = rd.Value[StockOpen];
}
if (rd.Value[StockHigh] > y1)
rd.Value[StockHigh] = y1;
if (rd.Value[StockLow] < y2)
rd.Value[StockLow] = y2;
rd.IsAlternate = (rd.Value[StockOpen] < rd.Value[StockClose]);
RenderVStockBoxWhisker(g, rd, x,
rd.Value[StockHigh], y1, HiLoBarSegment.HighWhisker);
RenderVStockBoxWhisker(g, rd, x,
y2, rd.Value[StockLow], HiLoBarSegment.LowWhisker);
RenderVStockBoxOpenClose(g, rd, x, y1, y2);
}
else
{
int y = (y1 != int.MinValue) ? y1 : y2;
if (y != int.MinValue)
{
if (y < rd.Value[StockHigh])
rd.Value[StockHigh] = y;
if (y > rd.Value[StockLow])
rd.Value[StockLow] = y;
}
if (y > rd.Value[StockHigh] && y < rd.Value[StockLow])
{
RenderVStockBoxWhisker(g, rd, x, rd.Value[StockHigh], y, HiLoBarSegment.HighWhisker);
RenderVStockBoxWhisker(g, rd, x, y, rd.Value[StockLow], HiLoBarSegment.LowWhisker);
RenderVStockBoxOpenClose(g, rd, x, y, y);
}
else
{
RenderVStockBoxWhisker(g, rd, x,
rd.Value[StockHigh], rd.Value[StockLow], HiLoBarSegment.CenterLine);
if (y != int.MinValue)
RenderVStockBoxOpenClose(g, rd, x, y, y);
}
}
}
#region RenderVStockBoxWhisker
private void RenderVStockBoxWhisker(Graphics g,
HiLoRenderData rd, int x, int y1, int y2, HiLoBarSegment segment)
{
if (y2 > y1)
{
Point pt1 = new Point(x, y1);
Point pt2 = new Point(x, y2 + 1);
RenderBoxWhisker(g, rd, pt1, pt2, segment);
}
}
#endregion
#region RenderVStockBoxOpenClose
private void RenderVStockBoxOpenClose(
Graphics g, HiLoRenderData rd, int x, int y1, int y2)
{
if (y2 == y1)
{
y1--;
y2++;
}
y2++;
Point pt1 = new Point(x - BarWidth / 2, y1);
Point pt2 = new Point(pt1.X + BarWidth, y2);
int lw = RenderStockBox(g, rd, pt1, pt2);
Rectangle r = new Rectangle(pt1.X, pt1.Y, pt2.X - pt1.X, pt2.Y - pt1.Y);
if (r.Width > 0 && r.Height > 0)
{
if (GetBarShading(rd.ChartXy) == true)
{
ChartControl chartControl = ChartControl;
if (chartControl.DoPreRenderSeriesHiloBarEvent(
g, rd.ChartXy, this, rd, pt1, pt2, HiLoBarSegment.BarShading) == false)
{
RenderVBarShading(g, r, r, BarSegment.Top);
chartControl.DoPostRenderSeriesHiLoBarEvent(
g, rd.ChartXy, this, rd, pt1, pt2, HiLoBarSegment.BarShading);
}
}
}
}
#endregion
#endregion
#region RenderVStockBoxMedian
private void RenderVStockBoxMedian(
Graphics g, HiLoRenderData rd, int x, int y1, int y2)
{
if (rd.Value.Length > StockMedian)
{
int y3 = rd.Value[StockMedian];
if (y3 > y1 && y3 < y2)
{
Point pt1 = new Point(x, y3);
Point pt2 = new Point(x + BarWidth - 1, y3);
ChartControl chartControl = ChartControl;
if (chartControl.DoPreRenderSeriesHiloBarEvent(
g, rd.ChartXy, this, rd, pt1, pt2, HiLoBarSegment.MedianLine) == false)
{
ChartLineVisualStyle lstyle = GetSegLineStyle(rd, HiLoBarSegment.MedianLine);
if (lstyle.LinePattern != LinePattern.None)
{
using (Pen pen = new Pen(lstyle.LineColor, lstyle.LineWidth))
{
if (lstyle.LinePattern != LinePattern.NotSet)
pen.DashStyle = (DashStyle)lstyle.LinePattern;
if (lstyle.LineWidth > 1)
pt2.X++;
g.DrawLine(pen, pt1, pt2);
}
}
chartControl.DoPostRenderSeriesHiLoBarEvent(
g, rd.ChartXy, this, rd, pt1, pt2, HiLoBarSegment.MedianLine);
}
}
}
}
#endregion
#region RenderVStockHiLo
private void RenderVStockHiLo(Graphics g, HiLoRenderData rd, int x)
{
int y1, y2, y3, y4;
NormalizeHiLoValues(rd, out y1, out y2, out y3, out y4);
ChartLineVisualStyle ostyle, cstyle;
NormalizeHiLoStyles(rd, out ostyle, out cstyle);
if (rd.Value[StockOpen] != int.MinValue)
{
Point pt1 = new Point(x - BarWidth / 2, y2);
Point pt2 = new Point(pt1.X + BarWidth / 2, pt1.Y);
RenderHiLoWhisker(g, rd, pt1, pt2, ostyle, HiLoBarSegment.OpenWhisker);
}
if (rd.Value[StockClose] != int.MinValue)
{
Point pt1 = new Point(x + 1, y3);
Point pt2 = new Point(pt1.X + BarWidth / 2, pt1.Y);
RenderHiLoWhisker(g, rd, pt1, pt2, cstyle, HiLoBarSegment.CloseWhisker);
}
NormalizeHiLoDir(rd, ref y2, ref y3, ref ostyle, ref cstyle);
if ((rd.IsAlternate == false && _RenderFullDefRange == true) ||
(rd.IsAlternate == true && _RenderFullAltRange == true))
{
RenderHiLoRange(g, rd,
new Point(x, y1), new Point(x, y4), HiLoBarSegment.FullRange);
}
else
{
if (y1 == y2 && y3 != y4)
y2 = y3;
// High segment
if (y2 > y1)
{
int n = (ostyle != null) ? ostyle.LineWidth / 2 : 0;
RenderHiLoRange(g, rd,
new Point(x, y1), new Point(x, y2 - n), HiLoBarSegment.HighWhisker);
}
// Low segment
if (y3 < y4)
{
int n = 0;
if (y3 == y1)
n = -cstyle.LineWidth / 2;
else if (y3 != y2)
n = (cstyle.LineWidth + 1) / 2;
RenderHiLoRange(g, rd,
new Point(x, y3 + n), new Point(x, y4), HiLoBarSegment.LowWhisker);
}
// Center segment.
if (y2 < y3 || (y1 == y2 && y3 == y4))
{
ChartLineVisualStyle y2Style = (y2 == rd.Value[StockOpen]) ? ostyle : cstyle;
ChartLineVisualStyle y3Style = (y3 == rd.Value[StockOpen]) ? ostyle : cstyle;
if (y2Style != null)
y2 -= (y2Style.LineWidth / 2);
if (y3Style != null)
y3 += ((y3Style.LineWidth + 1) / 2);
RenderHiLoRange(g, rd,
new Point(x, y2), new Point(x, y3), HiLoBarSegment.CenterLine);
}
}
}
#endregion
#endregion
#endregion
#region GetHStockValues
internal int[] GetHStockValues(ChartXy chartXy, SeriesPoint sp)
{
ChartAxis axis = AxisX ?? chartXy.AxisX;
int[] values = new int[Math.Max(4, sp.ValueY.Length)];
for (int i = 0; i < sp.ValueY.Length; i++)
values[i] = chartXy.GetDataPointX(axis, sp.ValueY[i]);
NormalizeStockValues(sp, values);
return (values);
}
#endregion
#region GetVStockValues
internal int[] GetVStockValues(ChartXy chartXy, SeriesPoint sp)
{
ChartAxis axis = AxisY ?? chartXy.AxisY;
int[] values = new int[Math.Max(4, sp.ValueY.Length)];
for (int i = 0; i < sp.ValueY.Length; i++)
values[i] = chartXy.GetDataPointY(axis, sp.ValueY[i]);
NormalizeStockValues(sp, values);
return (values);
}
#endregion
#region NormalizeStockValues
private void NormalizeStockValues(SeriesPoint sp, int[] values)
{
for (int i = sp.ValueY.Length; i < values.Length; i++)
values[i] = int.MinValue;
if (values[StockLow] == int.MinValue)
values[StockLow] = values[StockHigh];
if ((IsRotated == true && values[StockLow] > values[StockHigh]) ||
(IsRotated == false && values[StockLow] < values[StockHigh]))
{
int temp = values[StockLow];
values[StockLow] = values[StockHigh];
values[StockHigh] = temp;
}
}
#endregion
#region NormalizeHiLoValues
private void NormalizeHiLoValues(
HiLoRenderData rd, out int v1, out int v2, out int v3, out int v4)
{
v1 = rd.Value[StockHigh];
v4 = rd.Value[StockLow];
v2 = (rd.Value[StockOpen] != int.MinValue) ? rd.Value[StockOpen] : v1;
v3 = (rd.Value[StockClose] != int.MinValue) ? rd.Value[StockClose] : v4;
if (v1 > v4)
{
if (v1 <v2)
v1 = v2;
if (v4 > v3)
v4 = v3;
rd.IsAlternate = (v2 > v3);
}
else
{
if (v1 > v2)
v1 = v2;
if (v4 < v3)
v4 = v3;
rd.IsAlternate = (v2 < v3);
}
}
#endregion
#region NormalizeHiLoDir
private void NormalizeHiLoDir(HiLoRenderData rd,
ref int v1, ref int v2, ref ChartLineVisualStyle style1, ref ChartLineVisualStyle style2)
{
if (rd.IsAlternate == false)
{
int y = v1;
v1 = v2;
v2 = y;
ChartLineVisualStyle style = style1;
style1 = style2;
style2 = style1;
}
}
#endregion
#region NormalizeHiLoStyles
private void NormalizeHiLoStyles(HiLoRenderData rd,
out ChartLineVisualStyle ostyle, out ChartLineVisualStyle cstyle)
{
ostyle = (rd.Value[StockOpen] != int.MinValue) ? GetSegLineStyle(rd, HiLoBarSegment.OpenWhisker) : null;
cstyle = (rd.Value[StockClose] != int.MinValue) ? GetSegLineStyle(rd, HiLoBarSegment.CloseWhisker) : null;
rd.EndDelta = GetHiLoEndDelta(ostyle, cstyle);
}
#region GetHiLoEndDelta
private int GetHiLoEndDelta(
ChartLineVisualStyle ostyle, ChartLineVisualStyle cstyle)
{
int delta = 0;
if (ostyle != null)
{
if (ostyle.LineWidth > 1)
{
if (ostyle.LinePattern != LinePattern.None)
delta = (ostyle.LineWidth + 1) / 2;
}
}
if (cstyle != null)
{
if (cstyle.LineWidth > 1)
{
if (cstyle.LinePattern != LinePattern.None)
delta = Math.Max(delta, (cstyle.LineWidth + 1) / 2);
}
}
return (delta);
}
#endregion
#endregion
#region RenderBoxWhisker
private void RenderBoxWhisker(Graphics g,
HiLoRenderData rd, Point pt1, Point pt2, HiLoBarSegment segment)
{
ChartXy chartXy = rd.ChartXy;
ChartControl chartControl = ChartControl;
SmoothingMode sm = g.SmoothingMode;
g.SmoothingMode = SmoothingMode.None;
if (chartControl.DoPreRenderSeriesHiloBarEvent(g, chartXy, this, rd, pt1, pt2, segment) == false)
{
ChartLineVisualStyle lstyle = GetSegLineStyle(rd, segment);
if (lstyle.LinePattern != LinePattern.None)
{
using (Pen pen = new Pen(lstyle.LineColor, Dpi.Width(lstyle.LineWidth)))
{
if (lstyle.LinePattern != LinePattern.NotSet)
pen.DashStyle = (DashStyle)lstyle.LinePattern;
Point pt3 = pt2;
if (lstyle.LineWidth == 1)
{
if (pt1.X == pt2.X)
pt3.Y--;
else
pt3.X--;
}
g.DrawLine(pen, pt1, pt3);
}
}
chartControl.DoPostRenderSeriesHiLoBarEvent(g, chartXy, this, rd, pt1, pt2, segment);
}
if (rd.SeriesStyle.HiLoBarVisualStyle.ShowWhiskerCaps == Tbool.True)
RenderWhiskerCap(g, rd, pt1, pt2, segment);
g.SmoothingMode = sm;
}
#region RenderWhiskerCap
private void RenderWhiskerCap(Graphics g,
HiLoRenderData rd, Point pt1, Point pt2, HiLoBarSegment segment)
{
if (segment == HiLoBarSegment.HighWhisker || segment == HiLoBarSegment.LowWhisker)
{
HiLoBarSegment capSegment = (segment == HiLoBarSegment.HighWhisker)
? HiLoBarSegment.HighWhiskerCap : HiLoBarSegment.LowWhiskerCap;
GetWhiskerCapPoints(segment, ref pt1, ref pt2);
ChartControl chartControl = ChartControl;
if (chartControl.DoPreRenderSeriesHiloBarEvent(
g, rd.ChartXy, this, rd, pt1, pt2, capSegment) == false)
{
ChartLineVisualStyle lstyle = GetSegLineStyle(rd, capSegment);
if (lstyle.LinePattern != LinePattern.None)
{
using (Pen pen = new Pen(lstyle.LineColor, lstyle.LineWidth))
{
if (lstyle.LinePattern != LinePattern.NotSet)
pen.DashStyle = (DashStyle)lstyle.LinePattern;
if (lstyle.LineWidth == 1)
{
if (pt1.X == pt2.X)
pt2.Y--;
else
pt2.X--;
}
g.DrawLine(pen, pt1, pt2);
}
}
chartControl.DoPostRenderSeriesHiLoBarEvent(
g, rd.ChartXy, this, rd, pt1, pt2, capSegment);
}
}
}
#region GetWhiskerCapPoints
private void GetWhiskerCapPoints(
HiLoBarSegment segment, ref Point pt1, ref Point pt2)
{
int n = BarWidth / 3;
switch (segment)
{
case HiLoBarSegment.HighWhisker:
if (pt1.X == pt2.X)
{
pt1.X -= n;
pt2.X += n + 1;
pt2.Y = pt1.Y;
}
else
{
pt1.Y -= n;
pt2.Y += n + 1;
pt1.X = pt2.X;
}
break;
case HiLoBarSegment.LowWhisker:
if (pt1.X == pt2.X)
{
pt1.X -= n;
pt2.X += n + 1;
pt1.Y = pt2.Y;
}
else
{
pt1.Y -= n;
pt2.Y += n + 1;
pt2.X = pt1.X;
}
break;
}
}
#endregion
#endregion
#endregion
#region RenderStockBox
private int RenderStockBox(
Graphics g, HiLoRenderData rd, Point pt1, Point pt2)
{
int lineWidth = 0;
Rectangle r = new Rectangle(pt1.X, pt1.Y, pt2.X - pt1.X, pt2.Y - pt1.Y);
if (r.Width > 0 && r.Height > 0)
{
ChartXy chartXy = rd.ChartXy;
ChartControl chartControl = ChartControl;
SmoothingMode sm = g.SmoothingMode;
g.SmoothingMode = SmoothingMode.None;
if (chartControl.DoPreRenderSeriesHiloBarEvent(
g, chartXy, this, rd, pt1, pt2, HiLoBarSegment.Box) == false)
{
if (HiLoBarType == HiLoBarType.Box)
RenderStockBoxBackground(g, rd, r);
else
RenderStockCandleBackground(g, rd, r);
ChartLineVisualStyle lstyle = rd.DefaultStyle.BoxBorder;
if (CanUseAlternateSegmentStyle(rd) == true)
{
if (rd.IsAlternate == true && rd.AlternateStyle.BoxBorder.IsEmpty == false)
lstyle = rd.AlternateStyle.BoxBorder;
}
if (lstyle.LinePattern != LinePattern.None)
{
using (Pen pen = new Pen(lstyle.LineColor, Dpi.Width(lstyle.LineWidth)))
{
lineWidth = (int)pen.Width;
if (lstyle.LinePattern != LinePattern.NotSet)
pen.DashStyle = (DashStyle)lstyle.LinePattern;
if (pt1.X == pt2.X || pt1.Y == pt2.Y)
{
g.DrawLine(pen, pt1, pt2);
}
else
{
pen.Alignment = PenAlignment.Inset;
if (lstyle.LineWidth == 1)
{
r.Width--;
r.Height--;
}
if (r.Width > 0 && r.Height > 0)
g.DrawRectangle(pen, r);
}
}
}
chartControl.DoPostRenderSeriesHiLoBarEvent(
g, chartXy, this, rd, pt1, pt2, HiLoBarSegment.Box);
}
if (ShowHiLoBarMedianLines == true)
{
if (IsRotated == false)
RenderVStockBoxMedian(g, rd, r.X, r.Y, r.Bottom);
else
RenderHStockBoxMedian(g, rd, r.Y, r.X, r.Right);
}
g.SmoothingMode = sm;
}
return (lineWidth);
}
#region RenderStockCandleBackground
private void RenderStockCandleBackground(
Graphics g, HiLoRenderData rd, Rectangle r)
{
Background bk =
GetBoxBackground(rd, rd.AlternateStyle.BoxBackground, rd.DefaultStyle.BoxBackground);
if (bk.IsEmpty == false)
{
using (Brush br = bk.GetBrush(r))
g.FillRectangle(br, r);
}
}
#endregion
#region RenderStockBoxBackground
private void RenderStockBoxBackground(
Graphics g, HiLoRenderData rd, Rectangle r)
{
Background bkDef = rd.DefaultStyle.BoxBackground;
Background bkAlt = rd.AlternateStyle.BoxBackground;
if (bkAlt.IsEmpty == true)
bkAlt = bkDef;
if (rd.IsAlternate == true)
{
Background bkSave = bkDef;
bkDef = bkAlt;
bkAlt = bkSave;
}
if ((ShowHiLoBarMedianLines == true) && (rd.Value.Length > StockMedian))
{
if (bkAlt.IsEmpty == false)
{
if (IsRotated == false)
r = RenderVBox(g, rd.Value[StockMedian], bkAlt, r);
else
r = RenderHBox(g, rd.Value[StockMedian], bkAlt, r);
}
}
if (r.Width > 0 && r.Height > 0)
{
if (bkDef.IsEmpty == false)
{
using (Brush br = bkDef.GetBrush(r))
g.FillRectangle(br, r);
}
}
}
#region RenderVBox
private Rectangle RenderVBox(Graphics g, int y, Background bk, Rectangle r)
{
if ((y > r.Y && y < r.Bottom) && bk.IsEmpty == false)
{
int ry = r.Y;
r.Height = r.Bottom - y;
r.Y = y;
using (Brush br = bk.GetBrush(r))
g.FillRectangle(br, r);
r.Y = ry;
r.Height = y - ry;
}
return (r);
}
#endregion
#region RenderHBox
private Rectangle RenderHBox(Graphics g, int x, Background bk, Rectangle r)
{
if (x > r.X && x < r.Right)
{
int rw = r.Width;
r.Width = x - r.X;
using (Brush br = bk.GetBrush(r))
g.FillRectangle(br, r);
r.X = r.Right;
r.Width = rw - r.Width;
}
return (r);
}
#endregion
#endregion
#endregion
#region RenderHiLoWhisker
private ChartLineVisualStyle RenderHiLoWhisker(Graphics g,
HiLoRenderData rd, Point pt1, Point pt2, ChartLineVisualStyle style, HiLoBarSegment segment)
{
ChartXy chartXy = rd.ChartXy;
ChartControl chartControl = ChartControl;
SmoothingMode sm = g.SmoothingMode;
g.SmoothingMode = SmoothingMode.None;
if (chartControl.DoPreRenderSeriesHiloBarEvent(g, chartXy, this, rd, pt1, pt2, segment) == false)
{
if (style.LinePattern != LinePattern.None)
{
using (Pen pen = new Pen(style.LineColor, Dpi.Width(style.LineWidth)))
{
if (style.LinePattern != LinePattern.NotSet)
pen.DashStyle = (DashStyle)style.LinePattern;
if (style.LineWidth == 1)
{
if (pt1.X == pt2.X)
pt2.Y--;
else
pt2.X--;
}
g.DrawLine(pen, pt1, pt2);
}
}
chartControl.DoPostRenderSeriesHiLoBarEvent(g, chartXy, this, rd, pt1, pt2, segment);
}
g.SmoothingMode = sm;
return (style);
}
#endregion
#region RenderHiLoRange
private void RenderHiLoRange(
Graphics g, HiLoRenderData rd, Point pt1, Point pt2, HiLoBarSegment segment)
{
ChartXy chartXy = rd.ChartXy;
ChartControl chartControl = ChartControl;
if (pt1.X == pt2.X)
{
if (segment == HiLoBarSegment.HighWhisker || segment == HiLoBarSegment.FullRange)
pt1.Y -= rd.EndDelta;
if (segment == HiLoBarSegment.LowWhisker || segment == HiLoBarSegment.FullRange)
pt2.Y += rd.EndDelta;
}
else
{
if (segment == HiLoBarSegment.LowWhisker || segment == HiLoBarSegment.FullRange)
pt2.X -= rd.EndDelta;
if (segment == HiLoBarSegment.HighWhisker || segment == HiLoBarSegment.FullRange)
pt1.X += rd.EndDelta;
}
SmoothingMode sm = g.SmoothingMode;
g.SmoothingMode = SmoothingMode.None;
if (chartControl.DoPreRenderSeriesHiloBarEvent(g, chartXy, this, rd, pt1, pt2, segment) == false)
{
ChartLineVisualStyle lstyle = GetSegLineStyle(rd, segment);
if (lstyle.LinePattern != LinePattern.None)
{
using (Pen pen = new Pen(lstyle.LineColor, Dpi.Width(lstyle.LineWidth)))
{
if (lstyle.LinePattern != LinePattern.NotSet)
pen.DashStyle = (DashStyle)lstyle.LinePattern;
g.DrawLine(pen, pt1, pt2);
}
}
}
if (ShowHiLoBarMedianLines == true)
{
if (segment == HiLoBarSegment.CenterLine || segment == HiLoBarSegment.FullRange)
{
if (IsRotated == false)
RenderVStockBoxMedian(g, rd, pt1.X - BarWidth / 2, pt1.Y, pt2.Y);
else
RenderHStockBoxMedian(g, rd, pt1.Y - BarWidth / 2, pt2.X, pt1.X);
}
}
chartControl.DoPostRenderSeriesHiLoBarEvent(g, chartXy, this, rd, pt1, pt2, segment);
g.SmoothingMode = sm;
}
#endregion
#region GetSegLineStyle
private ChartLineVisualStyle GetSegLineStyle(HiLoRenderData rd, HiLoBarSegment segment)
{
ChartLineVisualStyle style = rd.DefaultStyle.Default;
if (CanUseAlternateSegmentStyle(rd) == true)
{
if (rd.IsAlternate == true && rd.AlternateStyle.Default.IsEmpty == false)
style = rd.AlternateStyle.Default;
}
switch (segment)
{
case HiLoBarSegment.FullRange:
break;
case HiLoBarSegment.Box:
if (rd.IsAlternate == true && rd.AlternateStyle.BoxBorder.IsEmpty == false)
{
style = rd.AlternateStyle.BoxBorder;
}
else
{
if (rd.DefaultStyle.BoxBorder.IsEmpty == false)
style = rd.DefaultStyle.BoxBorder;
}
break;
case HiLoBarSegment.MedianLine:
if (rd.IsAlternate == true && rd.AlternateStyle.MedianLine.IsEmpty == false)
{
style = rd.AlternateStyle.MedianLine;
}
else
{
if (rd.DefaultStyle.MedianLine.IsEmpty == false)
style = rd.DefaultStyle.MedianLine;
}
break;
case HiLoBarSegment.HighWhiskerCap:
if (rd.IsAlternate == true && rd.AlternateStyle.HighWhiskerCap.IsEmpty == false)
{
style = rd.AlternateStyle.HighWhiskerCap;
}
else
{
if (rd.DefaultStyle.HighWhiskerCap.IsEmpty == false)
style = rd.DefaultStyle.HighWhiskerCap;
}
break;
case HiLoBarSegment.LowWhiskerCap:
if (rd.IsAlternate == true && rd.AlternateStyle.LowWhiskerCap.IsEmpty == false)
{
style = rd.AlternateStyle.LowWhiskerCap;
}
else
{
if (rd.DefaultStyle.LowWhiskerCap.IsEmpty == false)
style = rd.DefaultStyle.LowWhiskerCap;
}
break;
case HiLoBarSegment.HighWhisker:
if (rd.IsAlternate == true && rd.AlternateStyle.HighWhisker.IsEmpty == false)
{
style = rd.AlternateStyle.HighWhisker;
}
else
{
if (rd.DefaultStyle.HighWhisker.IsEmpty == false)
style = rd.DefaultStyle.HighWhisker;
}
break;
case HiLoBarSegment.LowWhisker:
if (rd.IsAlternate == true && rd.AlternateStyle.LowWhisker.IsEmpty == false)
{
style = rd.AlternateStyle.LowWhisker;
}
else
{
if (rd.DefaultStyle.LowWhisker.IsEmpty == false)
style = rd.DefaultStyle.LowWhisker;
}
break;
case HiLoBarSegment.OpenWhisker:
if (rd.IsAlternate == true && rd.AlternateStyle.OpenWhisker.IsEmpty == false)
{
style = rd.AlternateStyle.OpenWhisker;
}
else
{
if (rd.DefaultStyle.OpenWhisker.IsEmpty == false)
style = rd.DefaultStyle.OpenWhisker;
}
break;
case HiLoBarSegment.CloseWhisker:
if (rd.IsAlternate == true && rd.AlternateStyle.CloseWhisker.IsEmpty == false)
{
style = rd.AlternateStyle.CloseWhisker;
}
else
{
if (rd.DefaultStyle.CloseWhisker.IsEmpty == false)
style = rd.DefaultStyle.CloseWhisker;
}
break;
case HiLoBarSegment.CenterLine:
if (rd.IsAlternate == true && rd.AlternateStyle.CenterLine.IsEmpty == false)
{
style = rd.AlternateStyle.CenterLine;
}
else
{
if (rd.DefaultStyle.CenterLine.IsEmpty == false)
style = rd.DefaultStyle.CenterLine;
}
break;
}
return (style);
}
#region CanUseAlternateSegmentStyle
private bool CanUseAlternateSegmentStyle(HiLoRenderData rd)
{
Tbool uas = rd.SeriesStyle.HiLoBarVisualStyle.UseAlternateSegmentStyle;
if (uas == Tbool.NotSet)
return (HiLoBarType == HiLoBarType.Candle);
return (uas == Tbool.True);
}
#endregion
#endregion
#region GetBoxBackground
private Background GetBoxBackground(HiLoRenderData rd, Background abk, Background sbk)
{
if (rd.IsAlternate == true && abk.IsEmpty == false)
return (abk);
return (sbk);
}
#endregion
#endregion
#region HighLightPoints
private bool HighLightPoints(ChartXy chartXy)
{
if (chartXy.ChartCrosshair.Visible == false)
return (false);
if (CrosshairHighlightPoints != Tbool.NotSet)
return (CrosshairHighlightPoints == Tbool.True);
return (chartXy.ChartCrosshair.HighlightPoints);
}
#endregion
#region GetHighlightStyle
private PointMarkerVisualStyle GetHighlightStyle(
ChartXy chartXy, ChartSeriesVisualStyle sstyle)
{
if (HighLightPoints(chartXy) == true)
{
PointMarkerVisualStyle pstyle = sstyle.MarkerVisualStyle;
PointMarkerVisualStyle hstyle = pstyle.Copy();
if (sstyle.MarkerHighlightVisualStyle.IsEmpty == false)
{
hstyle.ApplyStyle(sstyle.MarkerHighlightVisualStyle);
}
else
{
Size size = hstyle.Size;
size.Width += 4;
size.Height += 4;
hstyle.Size = size;
}
return (hstyle);
}
return (null);
}
#endregion
#region GetPointMarkerImage
private Image GetPointMarkerImage(
Graphics g, ChartXy chartXy, PointMarkerVisualStyle style)
{
Image image = PointMarkerImage;
if (image == null)
{
image = chartXy.GetPointMarker(g, style);
PointMarkerImage = image;
}
return (image);
}
#endregion
#region GetHighlightImage
private Image GetHighlightImage(
Graphics g, ChartXy chartXy, PointMarkerVisualStyle style)
{
Image image = PointMarkerHighlightImage;
if (image == null)
{
image = chartXy.GetPointMarker(g, style);
PointMarkerHighlightImage = image;
}
return (image);
}
#endregion
#region GetEmptyMarkerImage
private Image GetEmptyMarkerImage(
Graphics g, ChartXy chartXy, PointMarkerVisualStyle style)
{
Image image = PointMarkerEmptyImage;
if (image == null)
{
image = chartXy.GetPointMarker(g, style);
PointMarkerEmptyImage = image;
}
return (image);
}
#endregion
#region GatherSeriesPoints
private PointData GatherSeriesPoints(
ChartXy chartXy, SortedSeriesPoints ssp, int index, int count, bool allArgs)
{
if (_PointData == null)
_PointData = GatherSeriesPointsEx(chartXy, ssp, index, count, allArgs);
return (_PointData);
}
private PointData GatherSeriesPointsEx(
ChartXy chartXy, SortedSeriesPoints ssp, int index, int count, bool allArgs)
{
PointData pd = new PointData();
pd.Points = new List<Point[]>();
pd.SeriesPoints = new List<SeriesPoint[]>();
if (EnableEmptyValues == true)
{
PointData epd = new PointData();
epd.Points = new List<Point[]>();
epd.SeriesPoints = new List<SeriesPoint[]>();
int n = 0;
bool empty = false;
for (int i = 0; i < count; i++)
{
if (ssp[index + i].IsEmpty != empty)
{
int cnt = i - n;
if (cnt > 0)
GetPointList(chartXy, ssp, index + n, cnt, allArgs, empty ? epd : pd);
empty = !empty;
n = i;
}
}
if (n < count)
GetPointList(chartXy, ssp, index + n, count - n, allArgs, empty ? epd : pd);
_EmptyPointData = epd;
}
else
{
GetPointList(chartXy, ssp, index, count, allArgs, pd);
}
return (pd);
}
#endregion
#region GetPointList
private void GetPointList(ChartXy chartXy,
SortedSeriesPoints ssp, int index, int cnt, bool allArgs, PointData pd)
{
GetPointList(chartXy, ssp, index, cnt, 0, 0, allArgs, pd);
}
private void GetPointList(ChartXy chartXy, SortedSeriesPoints ssp,
int index, int cnt, int skip, int minDistance, bool allArgs, PointData pd)
{
if (cnt > 0)
{
Stack<object> stack = new Stack<object>();
skip++;
Point lpt = new Point(-5000, -5000);
if (allArgs == false)
{
if (cnt > skip && skip > 1)
cnt = (cnt + skip - 1) / skip;
for (int i = 0; i < cnt; i++)
{
int n = index + (i * skip);
if (n >= ssp.Count)
break;
SeriesPoint sp = ssp[n];
if (sp.Visible == true)
{
Point pt = chartXy.GetDataPointEx(this, sp, 0);
if (minDistance <= 0 || DataPointDistanceOk(lpt, pt, minDistance) == true)
{
stack.Push(sp);
stack.Push(pt);
lpt = pt;
}
}
}
}
else
{
int n = 0;
for (int i = 0; i < cnt; i++)
n += ssp[index + i].ValueY.Length;
n /= (n + skip - 1) / skip;
int m = 0;
for (int i = 0; i < cnt; i++)
{
SeriesPoint sp = ssp[index + i];
for (int j = 0; j < sp.ValueY.Length; j++)
{
if (m % skip == 0)
{
int w = m / skip;
Point pt = chartXy.GetDataPointNa(this, sp, j);
if (minDistance <= 0 || DataPointDistanceOk(lpt, pt, minDistance) == true)
{
stack.Push(sp);
stack.Push(pt);
lpt = pt;
}
}
m++;
}
}
}
if (stack.Count > 0)
{
int n = stack.Count / 2;
Point[] points = new Point[n];
SeriesPoint[] seriesPoints = new SeriesPoint[n];
for (int i = n - 1; i >= 0; i--)
{
points[i] = (Point)stack.Pop();
seriesPoints[i] = (SeriesPoint)stack.Pop();
}
pd.Points.Add(points);
pd.SeriesPoints.Add(seriesPoints);
}
}
}
#region DataPointDistanceOk
private bool DataPointDistanceOk(Point lpt, Point pt, int minDistance)
{
int dx = (lpt.X - pt.X);
int dy = (lpt.Y - pt.Y);
int h = (int)AMath.Sqrt(dx * dx + dy * dy);
return (h >= minDistance);
}
#endregion
#endregion
#endregion
#region Render
internal override void Render(ChartRenderInfo renderInfo)
{
if (Displayed == true)
{
Rectangle bounds = BoundsRelative;
if (renderInfo.ClipRectangle.IntersectsWith(bounds))
RenderOverride(renderInfo);
}
}
#endregion
#region RenderIndicators
internal void RenderIndicators(ChartRenderInfo renderInfo, bool onTop)
{
if (SeriesType != SeriesType.HorizontalDot || SeriesType != SeriesType.VerticalDot)
{
if (SeriesPoints.Count > 0)
{
Graphics g = renderInfo.Graphics;
ChartXy chartXy = Parent as ChartXy;
ChartSeriesVisualStyle sstyle = EffectiveChartSeriesStyle;
SortedSeriesPoints ssp = GetSortedSeriesPoints(chartXy);
foreach (ChartIndicator indicator in ChartIndicators)
{
if (indicator.DisplayOnTop == onTop)
{
if (indicator.IsDisplayed == true)
{
ssp.SlopeIndex = indicator.ValueYIndex;
switch (indicator.IndicatorType)
{
case ChartIndicatorType.RegressionLine:
RenderRegressionLine(g, chartXy, ssp, (RegressionLine)indicator);
break;
case ChartIndicatorType.TrendLine:
RenderTrendLine(g, chartXy, ssp, (TrendLine)indicator);
break;
}
}
}
}
}
}
}
#region RenderRegressionLine
private void RenderRegressionLine(Graphics g,
ChartXy chartXy, SortedSeriesPoints ssp, RegressionLine regline)
{
double m = regline.Slope;
double b = regline.Intercept;
if (m.Equals(double.NaN) == false && b.Equals(double.NaN) == false)
{
ChartAxis axis = AxisX ?? chartXy.AxisX;
double x1, x2;
switch (ActualScaleTypeX)
{
case ScaleType.DateTime:
x1 = chartXy.GetDateTimePointValue(axis, axis.TickmarkLayout, (DateTime)MinValueX);
x2 = chartXy.GetDateTimePointValue(axis, axis.TickmarkLayout, (DateTime)MaxValueX);
break;
default:
x1 = Convert.ToDouble(MinValueX);
x2 = Convert.ToDouble(MaxValueX);
break;
}
Point pt1 = chartXy.GetPointFromValue(this, MinValueX, m * x1 + b);
Point pt2 = chartXy.GetPointFromValue(this, MaxValueX, m * x2 + b);
if (SeriesType == SeriesType.VerticalBar ||
SeriesType == SeriesType.VerticalHiLoBar)
{
pt1.X += BarOffset;
pt2.X += BarOffset;
}
else if (SeriesType == SeriesType.HorizontalBar ||
SeriesType == SeriesType.HorizontalHiLoBar)
{
pt1.Y += BarOffset;
pt2.Y += BarOffset;
}
RegressionLineVisualStyle rstyle = regline.RegressionLineVisualStyle;
Color color = rstyle.LineColor;
if (color.IsEmpty)
color = DefaultPaletteColor;
using (Pen pen = new Pen(color, Dpi.Width(rstyle.LineWidth)))
{
if (rstyle.LinePattern != LinePattern.NotSet)
pen.DashStyle = (DashStyle)rstyle.LinePattern;
if (rstyle.StartCap != ChartLineCap.NotSet)
pen.StartCap = (LineCap)rstyle.StartCap;
if (rstyle.EndCap != ChartLineCap.NotSet)
pen.EndCap = (LineCap)rstyle.EndCap;
g.DrawLine(pen, pt1, pt2);
}
}
}
#endregion
#region RenderTrendLine
private void RenderTrendLine(Graphics g,
ChartXy chartXy, SortedSeriesPoints ssp, TrendLine trendLine)
{
SeriesPoint sp1 = ssp.GetSeriesPoint(trendLine.ValueX1);
SeriesPoint sp2 = ssp.GetSeriesPoint(trendLine.ValueX2);
if (sp1 != null && sp2 != null)
{
Point pt1 = chartXy.GetDataPointEx(this, sp1, trendLine.ValueYIndex);
Point pt2 = chartXy.GetDataPointEx(this, sp2, trendLine.ValueYIndex);
if (SeriesType == SeriesType.VerticalBar ||
SeriesType == SeriesType.VerticalHiLoBar)
{
pt1.X += BarOffset;
pt2.X += BarOffset;
}
else if (SeriesType == SeriesType.HorizontalBar ||
SeriesType == SeriesType.HorizontalHiLoBar)
{
pt1.Y += BarOffset;
pt2.Y += BarOffset;
}
if (pt1.X >= chartXy.ContentBounds.X && pt2.X < chartXy.ContentBounds.Right)
{
TrendLineVisualStyle tstyle = trendLine.TrendLineVisualStyle;
Color color = tstyle.LineColor;
if (color.IsEmpty)
color = DefaultPaletteColor;
using (Pen pen = new Pen(color, Dpi.Width(tstyle.LineWidth)))
{
if (tstyle.LinePattern != LinePattern.NotSet)
pen.DashStyle = (DashStyle)tstyle.LinePattern;
if (tstyle.StartCap != ChartLineCap.NotSet)
pen.StartCap = (LineCap)tstyle.StartCap;
if (tstyle.EndCap != ChartLineCap.NotSet)
pen.EndCap = (LineCap)tstyle.EndCap;
g.DrawLine(pen, pt1, pt2);
}
}
}
}
#endregion
#endregion
#region InvalidatePoints
internal void InvalidatePoints()
{
_PointData = null;
_EmptyPointData = null;
_ConvexHullPoints = null;
_StepPointData = null;
}
#endregion
#region InvalidatePointLabels
internal void InvalidatePointLabels()
{
ChartXy chartXy = Parent as ChartXy;
if (chartXy != null)
chartXy.InvalidatePointLabelsEx();
}
#endregion
#region RefreshSeries
///<summary>
/// Causes the series to refresh its display, as the underlying
/// series data (potentially) has changed in some way.
///</summary>
public void RefreshSeries()
{
SeriesRangeChanged = true;
InvalidateLayout();
}
#endregion
#region UpdateSeriesRange
internal void UpdateSeriesRange()
{
if (SeriesRangeChanged == true)
{
if (Parent == null)
return;
SeriesRangeChanged = false;
IsSorted = true;
QualitativeXValues.Clear();
QualitativeYValues.Clear();
_MinValueX = null;
_MinValueY = null;
_MaxValueX = null;
_MaxValueY = null;
if (SeriesPoints.Count > 0)
{
ChartXy chartXy = Parent as ChartXy;
Type dataTypeX = null;
Type dataTypeY = null;
if (ChartControl != null && ChartControl.DesignerHosted == true)
{
dataTypeX = GetDataTypeX(SeriesPoints);
dataTypeY = GetDataTypeY(SeriesPoints);
ActualScaleTypeX = GetActualScaleType(dataTypeX, ScaleTypeX);
ActualScaleTypeY = GetActualScaleType(dataTypeY, ScaleTypeY);
_PlotData = null;
}
for (int i = 0; i < SeriesPoints.Count; i++)
{
SeriesPoint sp = SeriesPoints[i];
if (sp.Visible == true)
{
UpdateXValueRange(chartXy, sp, ref dataTypeX);
switch (SeriesType)
{
case SeriesType.VerticalDot:
case SeriesType.HorizontalDot:
ActualScaleTypeY = ScaleType.Quantitative;
break;
case SeriesType.Bubble:
UpdateYBubbleRange(chartXy, sp, ref dataTypeY);
break;
default:
UpdateYValueRange(chartXy, sp, ref dataTypeY);
break;
}
}
}
if (SeriesType == SeriesType.VerticalDot ||
SeriesType == SeriesType.HorizontalDot)
{
UpdateStackedYValueRange();
}
else
{
if (QualitativeXValues.Count > 0)
{
_MinValueX = 0;
_MaxValueX = QualitativeXValues.Count - 1;
}
if (QualitativeYValues.Count > 0)
{
_MinValueY = 0;
_MaxValueY = QualitativeYValues.Count - 1;
}
}
}
}
}
#region GetDataTypeX
private Type GetDataTypeX(SeriesPointCollection spc)
{
Type dataType = null;
for (int i = 0; i < spc.Count; i++)
{
SeriesPoint sp = spc[i];
if (sp.Visible == true)
{
if (sp.ValueX != null)
{
dataType = sp.ValueX.GetType();
if (dataType != typeof(int))
break;
}
}
}
return (dataType);
}
#endregion
#region GetDataTypeY
private Type GetDataTypeY(SeriesPointCollection spc)
{
Type dataType = null;
for (int i = 0; i < spc.Count; i++)
{
SeriesPoint sp = spc[i];
if (sp.Visible == true)
{
if (sp.ValueY != null && sp.ValueY.Length > 0)
{
for (int j = 0; j < sp.ValueY.Length; j++)
{
object valueY = sp.ValueY[j];
if (valueY != null)
{
dataType = valueY.GetType();
if (dataType != typeof(int))
return (dataType);
}
}
}
}
}
return (dataType);
}
#endregion
#region UpdateXValueRange
private int _CmpLast;
private void UpdateXValueRange(ChartXy chartXy, SeriesPoint sp, ref Type dataType)
{
object value = sp.ValueX;
if (value != null)
{
if (dataType == null)
{
dataType = value.GetType();
ActualScaleTypeX = GetActualScaleType(dataType, ScaleTypeX);
}
else
{
if (value.GetType() != dataType)
{
if (ChartControl.DesignerHosted == true)
{
try
{
sp.ValueX = Convert.ChangeType(value, dataType);
}
catch
{
sp.ValueX = null;
}
value = sp.ValueX;
}
else
{
throw new Exception("Cannot mix ValueX data types (" +
dataType + "," + value.GetType() + ").");
}
}
}
switch (_ActualScaleTypeX)
{
case ScaleType.Qualitative:
if (QualitativeXValues.Contains(value) == false)
QualitativeXValues.Add(value);
break;
default:
if (_MinValueX == null)
{
_MinValueX = value;
_MaxValueX = value;
_CmpLast = 0;
}
else
{
if (chartXy.DataCompare(value, _MaxValueX) >= 0)
{
_MaxValueX = value;
if (_CmpLast == 0)
_CmpLast = 1;
else if (_CmpLast < 0)
IsSorted = false;
}
else
{
if (chartXy.DataCompare(value, _MinValueX) <= 0)
_MinValueX = value;
if (_CmpLast == 0)
_CmpLast = -1;
else if (_CmpLast > 0)
IsSorted = false;
}
}
break;
}
}
}
#endregion
#region UpdateYBubbleRange
private void UpdateYBubbleRange(ChartXy chartXy, SeriesPoint sp, ref Type dataType)
{
if (sp.ValueY == null || sp.ValueY.Length < 1)
throw new Exception("Invalid Bubble Chart 'Y' arguments.");
if (_PlotData == null)
_PlotData = new BubblePlotData();
BubblePlotData bdata = (BubblePlotData)_PlotData;
object value = sp.ValueY[0];
sp.IsEmptyValue = IsEmptyValue(value);
if (sp.IsEmpty == false)
{
if (dataType == null)
{
bdata.Clear();
dataType = value.GetType();
ActualScaleTypeY = GetActualScaleType(dataType, ScaleTypeY);
}
else
{
if (value.GetType() != dataType)
{
if (ChartControl.DesignerHosted == true)
{
sp.ValueY[0] = Convert.ChangeType(value, dataType);
value = sp.ValueY[0];
}
else
{
throw new Exception("Cannot mix ValueY data types (" +
dataType + "," + value.GetType() + ").");
}
}
}
ProcessYValueRange(chartXy, value);
if (sp.ValueY.Length > 1)
{
double bvalue = GetDoubleValue(sp.ValueY[1]);
bvalue = Math.Abs(bvalue);
if (bvalue < bdata.MinSize)
bdata.MinSize = bvalue;
if (bvalue > bdata.MaxSize)
bdata.MaxSize = bvalue;
bdata.TotalSize += bvalue;
if (sp.ValueY.Length > 2)
{
double ivalue = GetDoubleValue(sp.ValueY[2]);
if (ivalue < bdata.MinIntensity)
bdata.MinIntensity = ivalue;
if (ivalue > bdata.MaxIntensity)
bdata.MaxIntensity = ivalue;
}
}
}
}
#endregion
#region UpdateYValueRange
private void UpdateYValueRange(ChartXy chartXy, SeriesPoint sp, ref Type dataType)
{
if (sp.ValueY != null)
{
for (int j = 0; j < sp.ValueY.Length; j++)
{
object value = sp.ValueY[j];
sp.IsEmptyValue = IsEmptyValue(value);
if (sp.IsEmpty == false)
{
if (dataType == null)
{
dataType = value.GetType();
ActualScaleTypeY = GetActualScaleType(dataType, ScaleTypeY);
}
else
{
if (value.GetType() != dataType)
{
if (ChartControl.DesignerHosted == true)
{
try
{
sp.ValueY[j] = Convert.ChangeType(value, dataType);
}
catch
{
sp.ValueY[j] = null;
}
value = sp.ValueY[j];
}
else
{
throw new Exception("Cannot mix ValueY data types (" +
dataType + "," + value.GetType() + ").");
}
}
}
ProcessYValueRange(chartXy, value);
}
}
}
else
{
sp.IsEmptyValue = true;
}
}
#region IsEmptyValue
private bool IsEmptyValue(object value)
{
if (value == null)
return (true);
if (EmptyValues != null)
{
Type dataType = value.GetType();
for (int i = 0; i < EmptyValues.Length; i++)
{
if (EmptyValues[i] != null)
{
if (dataType == EmptyValues[i].GetType())
{
if (value.Equals(EmptyValues[i]) == true)
return (true);
}
}
}
}
return (false);
}
#endregion
#endregion
#region UpdateStackedYValueRange
private void UpdateStackedYValueRange()
{
if (QualitativeXValues.Count > 0 || QualitativeYValues.Count > 0)
throw new Exception("Dot plots can not contain Qualitative values.");
Dictionary<object, double> pd = new Dictionary<object, double>();
for (int i = 0; i < SeriesPoints.Count; i++)
{
SeriesPoint sp = SeriesPoints[i];
if (sp.Visible == true)
{
object ox = sp.ValueX;
double count = 0;
if (sp.ValueY != null && sp.ValueY.Length > 0)
{
foreach (object oy in sp.ValueY)
{
sp.IsEmptyValue = IsEmptyValue(oy);
if (sp.IsEmpty == false)
count += GetDoubleValue(oy);
}
}
else
{
if (sp.IsEmpty == false)
count++;
}
if (sp.IsEmpty == false)
{
if (pd.ContainsKey(ox) == true)
pd[ox] += count;
else
pd.Add(ox, count);
}
}
}
double maxValue = 0;
foreach (KeyValuePair<object, double> kvp in pd)
{
if (kvp.Value > maxValue)
maxValue = kvp.Value;
}
_MinValueY = 0.0;
_MaxValueY = maxValue;
}
#endregion
#region ProcessYValueRange
private void ProcessYValueRange(ChartXy chartXy, object value)
{
switch (_ActualScaleTypeY)
{
case ScaleType.Qualitative:
if (QualitativeYValues.Contains(value) == false)
QualitativeYValues.Add(value);
break;
default:
if (_MinValueY == null)
{
_MinValueY = value;
_MaxValueY = value;
}
else
{
int cmpMax = chartXy.DataCompare(value, _MaxValueY);
if (cmpMax >= 0)
{
_MaxValueY = value;
}
else
{
int cmpMin = chartXy.DataCompare(value, _MinValueY);
if (cmpMin <= 0)
_MinValueY = value;
}
}
break;
}
}
#endregion
#region GetActualScaleType
private ScaleType GetActualScaleType(Type dataType, ScaleType scaleType)
{
ScaleType autoType = SeriesPoint.GetScaleType(dataType);
if (scaleType == ScaleType.NotSet || scaleType == ScaleType.Auto)
return (autoType);
if (scaleType == autoType)
return (scaleType);
if (scaleType == ScaleType.Qualitative)
return (scaleType);
throw new Exception("Set ScaleType is incompatible with series data.");
}
#endregion
#endregion
#region ResetSortedPoints
internal void ResetSortedPoints()
{
if (IsSorted == false)
_SortedSeriesPoints = null;
}
#endregion
#region GetValueX
internal object GetValueX(SeriesPoint sp)
{
if (IsRotated == false)
return (sp.ValueX);
if (sp.ValueY != null && sp.ValueY.Length > 0)
return (sp.ValueY[0]);
return (null);
}
#endregion
#region GetValueY
internal object GetValueY(SeriesPoint sp, int index)
{
if (IsRotated == true)
return (sp.ValueX);
if (sp.ValueY != null && sp.ValueY.Length > index)
return (sp.ValueY[index]);
return (null);
}
#endregion
#region GetQualitativeValueX
internal object GetQualitativeValueX(int index)
{
if (IsRotated == false)
{
if (QualitativeXValues != null && QualitativeXValues.Count > index)
return (QualitativeXValues[index]);
}
else
{
if (QualitativeYValues != null && QualitativeYValues.Count > index)
return (QualitativeYValues[index]);
}
return (null);
}
#endregion
#region GetQualitativeValueY
internal object GetQualitativeValueY(int index)
{
if (IsRotated == true)
{
if (QualitativeXValues != null && QualitativeXValues.Count > index)
return (QualitativeXValues[index]);
}
else
{
if (QualitativeYValues != null && QualitativeYValues.Count > index)
return (QualitativeYValues[index]);
}
return (null);
}
#endregion
#region GetDoubleValue
private double GetDoubleValue(object value)
{
if (value is double)
return (double)value;
return (Convert.ToDouble(value));
}
#endregion
#region GetBarWidthRatio
internal double GetBarWidthRatio(ChartXy chartXy)
{
return (_BarWidthRatio > 0 ? _BarWidthRatio :
(chartXy.BarWidthRatio > 0 ? chartXy.BarWidthRatio : 1));
}
#endregion
#region GetPointLabels
internal List<PointLabel> GetPointLabels(Graphics g)
{
ChartXy chartXy = Parent as ChartXy;
PointLabelDisplayMode plmode = GetPointLabelDisplayType(chartXy);
if (plmode != PointLabelDisplayMode.None)
{
ChartSeriesVisualStyle sstyle = EffectiveChartSeriesStyle;
SortedSeriesPoints ssp = GetSortedSeriesPoints(chartXy);
ssp.SeriesLayoutCount = chartXy.SeriesLayoutCount;
ChartAxis axisX = (IsRotated == true) ? AxisY ?? chartXy.AxisY : AxisX ?? chartXy.AxisX;
ChartAxis axisY = (IsRotated == true) ? AxisX ?? chartXy.AxisX : AxisY ?? chartXy.AxisY;
if (ssp.Count > 0)
{
DataLabelVisualStyle dstyle = EffectiveDataLabelStyle;
PointData pd = GetLabelPoints(chartXy, ssp, 0, ssp.Count, plmode);
List<PointLabel> plabels = new List<PointLabel>();
if (pd.Points.Count > 0)
{
for (int i = 0; i < pd.Points.Count; i++)
{
Point[] pts = pd.Points[i];
SeriesPoint[] spts = pd.SeriesPoints[i];
for (int j = 0; j < pts.Length; j++)
{
SeriesPoint sp = spts[j];
Point pt = pts[j];
if (IsBarSeries == true && ShowOriginValueLabels == false)
{
if (IsBarOrigin(chartXy, sp) == true)
continue;
}
string text = GetPointLabelText(sp, axisX, axisY, dstyle);
PointLabel pl = new PointLabel(sp, pt, text);
pl.LabelSize = MeasurePointLabel(g, pl);
plabels.Add(pl);
}
}
}
if ((plmode & PointLabelDisplayMode.DataLabels) == PointLabelDisplayMode.DataLabels)
GetDataLabels(g, plabels, chartXy, axisX, axisY, dstyle);
return (plabels);
}
}
return (null);
}
#region GetPointLabelDisplayType
private PointLabelDisplayMode GetPointLabelDisplayType(ChartXy chartXy)
{
PointLabelDisplayMode ptype = PointLabelDisplayMode;
if (ptype != PointLabelDisplayMode.NotSet)
return (ptype);
ptype = chartXy.PointLabelDisplayMode;
return (ptype != PointLabelDisplayMode.NotSet ? ptype : PointLabelDisplayMode.None);
}
#endregion
#region GetLabelPoints
/// <summary>
/// Gets the collection of series PointData for the given PointLabelDisplayType.
/// </summary>
/// <param name="plmode"></param>
/// <returns></returns>
public PointData GetLabelPoints(PointLabelDisplayMode displayType)
{
ChartXy chartXy = Parent as ChartXy;
if (chartXy != null)
{
SortedSeriesPoints ssp = GetSortedSeriesPoints(chartXy);
return (GetLabelPoints(chartXy, ssp, 0, ssp.Count, displayType));
}
return (null);
}
private PointData GetLabelPoints(ChartXy chartXy,
SortedSeriesPoints ssp, int index, int count, PointLabelDisplayMode displayType)
{
PointData pd = new PointData();
pd.Points = new List<Point[]>();
pd.SeriesPoints = new List<SeriesPoint[]>();
if ((displayType & PointLabelDisplayMode.AllSeriesPoints) == PointLabelDisplayMode.AllSeriesPoints)
GetPointList(chartXy, ssp, index, count, _PointLabelSkip, _PointLabelMinDistance, false, pd);
else if ((displayType & ~PointLabelDisplayMode.AllSeriesPoints) != 0)
{
List<SeriesPoint> lmmsp = new List<SeriesPoint>();
if ((displayType & PointLabelDisplayMode.MinValueX) == PointLabelDisplayMode.MinValueX)
{
int n;
if (IsRotated == true)
{
if (QualitativeYValues.Count > 0)
n = (int)MinValueX;
else
n = ssp.SearchY(MinValueX);
}
else
{
if (QualitativeXValues.Count > 0)
n = (int)MinValueX;
else
n = (ssp.IsSorted == true) ? 0 : ssp.SearchX(MinValueX);
}
if (n >= 0)
lmmsp.Add(ssp[n]);
}
if ((displayType & PointLabelDisplayMode.MaxValueX) == PointLabelDisplayMode.MaxValueX)
{
int n;
if (IsRotated == true)
{
if (QualitativeYValues.Count > 0)
n = (int)MaxValueX;
else
n = ssp.SearchY(MaxValueX);
}
else
{
if (QualitativeXValues.Count > 0)
n = (int)MaxValueX;
else
n = (ssp.IsSorted == true) ? ssp.Count - 1 : ssp.SearchX(MaxValueX);
}
if (n >= 0 && lmmsp.Contains(ssp[n]) == false)
lmmsp.Add(ssp[n]);
}
if ((displayType & PointLabelDisplayMode.MinValueY) == PointLabelDisplayMode.MinValueY)
{
int n;
if (IsRotated == true)
{
if (QualitativeXValues.Count > 0)
n = (int)MinValueY;
else
n = (ssp.IsSorted == true) ? 0 : ssp.SearchX(MinValueY);
}
else
{
if (QualitativeYValues.Count > 0)
n = (int)MinValueY;
else
n = ssp.SearchY(MinValueY);
}
if (n >= 0 && lmmsp.Contains(ssp[n]) == false)
lmmsp.Add(ssp[n]);
}
if ((displayType & PointLabelDisplayMode.MaxValueY) == PointLabelDisplayMode.MaxValueY)
{
int n;
if (IsRotated == true)
{
if (QualitativeXValues.Count > 0)
n = (int)MaxValueY;
else
n = ssp.SearchX(MaxValueY);
}
else
{
if (QualitativeYValues.Count > 0)
n = (int)MaxValueY;
else
n = ssp.SearchY(MaxValueY);
}
if (n >= 0 && lmmsp.Contains(ssp[n]) == false)
lmmsp.Add(ssp[n]);
}
if (lmmsp.Count > 0)
{
SeriesPoint[] mmsp = new SeriesPoint[lmmsp.Count];
Point[] mmpt = new Point[lmmsp.Count];
for (int i = 0; i < lmmsp.Count; i++)
{
mmsp[i] = lmmsp[i];
mmpt[i] = chartXy.GetDataPointNa(this, lmmsp[i], 0);
}
pd.SeriesPoints.Add(mmsp);
pd.Points.Add(mmpt);
}
}
return (pd);
}
#endregion
#region GetDataLabels
private void GetDataLabels(Graphics g, List<PointLabel> plabels,
ChartXy chartXy, ChartAxis axisX, ChartAxis axisY, DataLabelVisualStyle dstyle)
{
foreach (DataLabel dlabel in DataLabels)
{
DataLabelVisualStyle xstyle = dlabel.EffectiveDataLabelStyle;
PointLabel pl = FindPointLabel(plabels, dlabel);
if (pl != null)
{
if (string.IsNullOrEmpty(dlabel.Text) == false)
pl.Label = dlabel.Text;
pl.DataLabelVisualStyle = xstyle;
pl.BarLabelPosition = dlabel.BarLabelPosition;
pl.LabelSize = MeasurePointLabel(g, pl);
}
else
{
SeriesPoint sp = new SeriesPoint(dlabel.ValueX, dlabel.ValueY);
string label = (string.IsNullOrEmpty(dlabel.Text) == false) ? dlabel.Text :
GetPointLabelText(sp, axisX, axisY, xstyle);
Point pt = chartXy.GetDataPointNa(this, sp, 0);
pl = new PointLabel(sp, pt, label);
pl.IsDataLabel = true;
pl.DataLabelVisualStyle = xstyle;
pl.BarLabelPosition = dlabel.BarLabelPosition;
pl.LabelSize = MeasurePointLabel(g, pl);
plabels.Add(pl);
}
}
}
#region FindPointLabel
private PointLabel FindPointLabel(List<PointLabel> plabels, DataLabel dlabel)
{
for (int i = 0; i < plabels.Count; i++)
{
SeriesPoint sp = plabels[i].SeriesPoint;
if ((sp.ValueX != null) &&
(sp.ValueY != null && sp.ValueY.Length > 0) &&
(sp.ValueX.Equals(dlabel.ValueX) && sp.ValueY[0].Equals(dlabel.ValueY)))
{
return (plabels[i]);
}
}
return (null);
}
#endregion
#endregion
#region IsBarOrigin
internal bool IsBarOrigin(ChartXy chartXy, SeriesPoint sp)
{
object value = ((sp.ValueY != null && sp.ValueY.Length > 1) ? sp.ValueY[1] : (chartXy.BarOrigin ?? 0));
ChartAxis axis = AxisY ?? chartXy.AxisY;
switch (axis.ScaleType)
{
case ScaleType.Quantitative:
double d1 = Convert.ToDouble(value);
double d2 = Convert.ToDouble(sp.ValueY[0]);
return (d1.Equals(d2));
case ScaleType.Qualitative:
string s1 = axis.QualitativeValues[0] as string;
string s2 = sp.ValueY[0] as string;
if (s1 != null)
return (s1.Equals(s2));
break;
}
return (false);
}
#endregion
#region GetPointLabelText
private string GetPointLabelText(SeriesPoint sp,
ChartAxis axisX, ChartAxis axisY, DataLabelVisualStyle dstyle)
{
string pattern = dstyle.TextFormat;
if (string.IsNullOrEmpty(pattern) == true)
return (GetDefaultPointLabelText(sp, axisX, axisY, dstyle));
pattern = pattern.Replace("\\n", "\n");
pattern = pattern.Replace("\\r", "\r");
Regex regex = new Regex("{([^}]*)}");
MatchCollection mc = regex.Matches(pattern);
StringBuilder sb = new StringBuilder();
int index = 0;
foreach (Match ma in mc)
{
if (ma.Index > index)
sb.Append(pattern.Substring(index, ma.Index - index));
sb.Append(ProcessFormatSpecifier(sp, axisX, axisY, ma.Value));
index = ma.Index + ma.Length;
}
if (index < pattern.Length)
sb.Append(pattern.Substring(index));
return (sb.ToString());
}
#region ProcessFormatSpecifier
private string ProcessFormatSpecifier(
SeriesPoint sp, ChartAxis axisX, ChartAxis axisY, string pattern)
{
string s = pattern.Substring(1, pattern.Length - 2);
int n = s.IndexOf(':');
if ((uint)n > s.Length - 1)
n = s.Length;
string placeHolder = s.Substring(0, n).Trim().ToUpper();
string formatSpecifier = (n + 1 < s.Length) ? s.Substring(n + 1) : "";
try
{
switch (placeHolder)
{
case "X":
return (GetPointLabelText(sp.ValueX, axisX, formatSpecifier));
case "Y":
case "Y0":
if (sp.ValueY != null && sp.ValueY.Length > 0)
return (GetPointLabelText(sp.ValueY[0], axisY, formatSpecifier));
return ("");
case "S":
if (string.IsNullOrEmpty(formatSpecifier) == false)
return (String.Format(formatSpecifier, Name));
return (Name);
default:
if (placeHolder.StartsWith("Y") == true)
{
int index = int.Parse(placeHolder.Substring(1));
if (sp.ValueY != null && sp.ValueY.Length > index)
return (GetPointLabelText(sp.ValueY[index], axisY, formatSpecifier));
}
return (s);
}
}
catch
{
}
return (s);
}
#endregion
#region GetDefaultPointLabelText
private string GetDefaultPointLabelText(SeriesPoint sp,
ChartAxis axisX, ChartAxis axisY, DataLabelVisualStyle dstyle)
{
String text = string.Empty;
if (IsBarSeries == true)
{
text = GetPointLabelText(sp.ValueY[0], axisY, string.Empty);
}
else
{
text = GetPointLabelText(sp.ValueX, axisX, string.Empty);
if (sp.ValueY != null)
text += " : " + GetPointLabelText(sp.ValueY[0], axisY, string.Empty);
}
return (text);
}
#endregion
#region GetPointLabelText
private string GetPointLabelText(
object value, ChartAxis axis, string format)
{
switch (axis.ScaleType)
{
case ScaleType.DateTime:
if (string.IsNullOrEmpty(format) == false)
{
if (value is DateTime)
{
DateTime date = (DateTime)value;
return (date.ToString(format));
}
}
return (GetDateTimeLabelText(axis, (DateTime)value));
case ScaleType.Qualitative:
if (string.IsNullOrEmpty(format) == false)
return (string.Format(format, value));
return (value.ToString());
default:
double d = Convert.ToDouble(value);
if (string.IsNullOrEmpty(format) == false)
return (d.ToString(format));
return (d.ToString("F3"));
}
}
#region GetDateTimeLabelText
internal string GetDateTimeLabelText(ChartAxis axis, DateTime dt)
{
switch (axis.ActualDateTimeUnits)
{
case DateTimeUnits.Ticks:
return (dt.Ticks.ToString());
case DateTimeUnits.Milliseconds:
return (dt.Millisecond.ToString());
case DateTimeUnits.Seconds:
return (dt.Second.ToString());
case DateTimeUnits.Minutes:
return (dt.Minute.ToString());
case DateTimeUnits.Hours:
return (dt.ToShortTimeString());
case DateTimeUnits.Days:
return (dt.ToShortDateString());
case DateTimeUnits.Months:
return (dt.Year + " " + dt.Month);
default:
return (dt.Year.ToString());
}
}
#endregion
#endregion
#endregion
#region MeasurePointLabel
internal Size MeasurePointLabel(Graphics g, PointLabel pl)
{
DataLabelVisualStyle dstyle = GetPointLabelVisualStyle(pl);
int width = (dstyle.MaxTextWidth > 0) ? dstyle.MaxTextWidth : 0;
using (StringFormat sf = new StringFormat())
{
if (dstyle.MaxTextLineCount <= 1)
sf.FormatFlags |= StringFormatFlags.NoWrap;
Size size = g.MeasureString(pl.Label, dstyle.Font, width, sf).ToSize();
size.Width++;
if (dstyle.MaxTextLineCount > 1)
{
int lineHeight = (int)(Math.Ceiling(dstyle.Font.GetHeight())) * dstyle.MaxTextLineCount;
if (size.Height > lineHeight)
size.Height = lineHeight;
}
return (size);
}
}
#region GetPointLabelVisualStyle
internal DataLabelVisualStyle GetPointLabelVisualStyle(PointLabel pl)
{
DataLabelVisualStyle dstyle = EffectiveDataLabelStyle.Copy();
if (pl.DataLabelVisualStyle != null)
dstyle.ApplyStyle(pl.DataLabelVisualStyle);
else
dstyle = EffectiveDataLabelStyle;
return (dstyle);
}
#endregion
#endregion
#endregion
#region GetRotateDegrees
internal RotateDegrees GetRotateDegrees(DataLabelVisualStyle dstyle)
{
RotateDegrees degrees = dstyle.RotateDegrees;
if (degrees == RotateDegrees.Auto || degrees == RotateDegrees.NotSet)
{
switch (SeriesType)
{
case SeriesType.HorizontalBar:
case SeriesType.HorizontalHiLoBar:
return (RotateDegrees.None);
case SeriesType.VerticalBar:
case SeriesType.VerticalHiLoBar:
return (RotateDegrees.Rotate270);
default:
return (RotateDegrees.None);
}
}
return (dstyle.RotateDegrees);
}
#endregion
#region IsConvexHullPoint
/// <summary>
/// Determines whether the given SeriesPoint is a ConvexHull point.
/// </summary>
/// <param name="sp"></param>
/// <returns></returns>
public bool IsConvexHullPoint(SeriesPoint sp)
{
if (sp != null && _ConvexHullPoints != null)
{
ChartXy chartXy = Parent as ChartXy;
if (chartXy != null)
{
ConvexHullDisplayMode mode = GetConvexHullDisplayMode(chartXy);
if (mode != ConvexHullDisplayMode.None)
{
foreach (Point ptc in _ConvexHullPoints)
{
if (ptc.Equals(sp.Point[0]) == true)
return (true);
}
}
}
}
return (false);
}
#endregion
#region IsHighLightPoint
/// <summary>
/// Determines if the given SeriesPoint is a HighLight Point (a
/// point highlighted by the Crosshair setup).
/// </summary>
/// <param name="sp"></param>
/// <returns></returns>
public bool IsHighLightPoint(SeriesPoint sp)
{
if (sp != null)
{
ChartXy chartXy = Parent as ChartXy;
if (chartXy != null)
return (chartXy.IsCrosshairSeriesPoint(this, sp.Point[0]));
}
return (false);
}
#endregion
#region Style handling
#region ApplyStyles
internal override void ApplyStyles(BaseVisualStyle style)
{
ChartSeriesVisualStyle sstyle = style as ChartSeriesVisualStyle;
if (sstyle != null)
{
ApplyParentStyles(sstyle, Parent as ChartContainer);
sstyle.ApplyStyle(ChartSeriesVisualStyle);
ApplyDefaultLineStyles(sstyle.LineStyle);
ApplyDefaultLineStyles(sstyle.SplineStyle);
ApplyDefaultLineStyles(sstyle.StepLineStyle);
ApplyDefaultLineStyles(sstyle.EmptyStyle);
ApplyDefaultMarkerStyles(sstyle.MarkerVisualStyle);
ApplyDefaultMarkerStyles(sstyle.MarkerEmptyVisualStyle);
if (sstyle.EmptyAreaBackground.IsEmpty)
sstyle.EmptyAreaBackground = new Background(Color.FromArgb(100, Color.LightGray));
if (SeriesType == SeriesType.Bubble)
{
if (sstyle.MarkerVisualStyle.Background.IsEmpty)
sstyle.MarkerVisualStyle.Background = new Background(DefaultPaletteColor);
}
ApplyDefaultBarStyles(sstyle.BarVisualStyle);
ApplyDefaultOhlcBarStyles(sstyle.HiLoBarVisualStyle);
}
else if (style is DataLabelVisualStyle)
{
DataLabelVisualStyle dstyle = (DataLabelVisualStyle)style;
ApplyParentStyles(dstyle, Parent as ChartContainer);
dstyle.ApplyStyle(_DataLabelVisualStyle);
dstyle.ApplyDefaults();
}
}
#region ApplyParentStyles (ChartSeriesVisualStyle)
private void ApplyParentStyles(
ChartSeriesVisualStyle pstyle, ChartContainer item)
{
if (item != null)
{
ApplyParentStyles(pstyle, item.Parent as ChartContainer);
if (item is BaseChart)
pstyle.ApplyStyle(((BaseChart)item).ChartSeriesVisualStyle);
if (item is ChartPanel)
pstyle.ApplyStyle(((ChartPanel)item).DefaultVisualStyles.ChartSeriesVisualStyle);
}
else
{
pstyle.ApplyStyle(ChartControl.BaseVisualStyles.ChartPanelVisualStyle);
pstyle.ApplyStyle(ChartControl.DefaultVisualStyles.ChartPanelVisualStyle);
}
}
#endregion
#region ApplyParentStyles (DataLabelVisualStyle)
private void ApplyParentStyles(
DataLabelVisualStyle dstyle, ChartContainer item)
{
if (item != null)
{
ApplyParentStyles(dstyle, item.Parent as ChartContainer);
if (item is BaseChart)
dstyle.ApplyStyle(((BaseChart)item).DataLabelVisualStyle);
if (item is ChartPanel)
dstyle.ApplyStyle(((ChartPanel)item).DefaultVisualStyles.DataLabelVisualStyle);
}
else
{
dstyle.ApplyStyle(ChartControl.BaseVisualStyles.DataLabelVisualStyle);
dstyle.ApplyStyle(ChartControl.DefaultVisualStyles.DataLabelVisualStyle);
}
}
#endregion
#region ApplyDefaultLineStyles
private void ApplyDefaultLineStyles(ChartLineVisualStyle lstyle)
{
if (lstyle.LineColor.IsEmpty == true)
lstyle.LineColor = DefaultPaletteColor;
lstyle.ApplyDefaults();
}
#endregion
#region ApplyDefaultMarkerStyles
private void ApplyDefaultMarkerStyles(PointMarkerVisualStyle pstyle)
{
if (pstyle.Background.IsEmpty && pstyle.BorderColor.IsEmpty)
pstyle.BorderColor = DefaultPaletteColor;
pstyle.ApplyDefaults();
}
#endregion
#region ApplyDefaultBarStyles
private void ApplyDefaultBarStyles(ChartBarVisualStyle bstyle)
{
if (bstyle.Background.IsEmpty == true)
bstyle.Background = new Background(DefaultPaletteColor);
ApplyDefaultLineStyles(bstyle.Border);
}
#endregion
#region ApplyDefaultOhlcBarStyles
private void ApplyDefaultOhlcBarStyles(ChartHiLoBarVisualStyle bstyle)
{
HiLoBarSegmentStyle sstyle = bstyle.DefaultSegmentStyle;
if (sstyle.Default.LineColor.IsEmpty == true)
sstyle.Default.LineColor = Color.Black;
sstyle.Default.ApplyDefaults();
switch (HiLoBarType)
{
case HiLoBarType.Candle:
bool backSet = (sstyle.BoxBackground.IsEmpty == true);
if (backSet == true)
sstyle.BoxBackground = new Background(DefaultPaletteColor);
Background bk = sstyle.BoxBackground;
sstyle = bstyle.AlternateSegmentStyle;
if (sstyle.BoxBackground.IsEmpty == true)
{
if (backSet == true)
{
sstyle.BoxBackground = new Background(Color.Black, DefaultPaletteColor);
sstyle.BoxBackground.HatchFillType = HatchFillType.ForwardDiagonal;
}
else
{
if (bk.IsSolidBrush == true)
{
sstyle.BoxBackground = new Background(Color.Black, bk.Color1);
sstyle.BoxBackground.HatchFillType = HatchFillType.ForwardDiagonal;
}
else if (bk.Color1.IsEmpty == false && bk.Color2.IsEmpty == false)
{
sstyle.BoxBackground = new Background(bk.Color2, bk.Color1);
}
}
}
break;
case Charts.HiLoBarType.Box:
if (sstyle.BoxBackground.IsEmpty == true)
sstyle.BoxBackground = new Background(DefaultPaletteColor);
break;
}
sstyle = bstyle.DefaultSegmentStyle;
_RenderFullDefRange = sstyle.CenterLine.IsEmpty &&
sstyle.HighWhisker.IsEmpty && sstyle.LowWhisker.IsEmpty;
sstyle = bstyle.AlternateSegmentStyle;
_RenderFullAltRange = sstyle.CenterLine.IsEmpty &&
sstyle.HighWhisker.IsEmpty && sstyle.LowWhisker.IsEmpty;
}
private bool _RenderFullDefRange;
private bool _RenderFullAltRange;
#endregion
#endregion
#region InvalidateStyle
///<summary>
///Invalidate the cached Style definition
///</summary>
public void InvalidateStyle()
{
if (_EffectiveChartSeriesStyle.InvalidateStyle() == true)
InvalidateLayout();
_EffectiveDataLabelStyle.InvalidateStyle();
foreach (DataLabel dl in DataLabels)
dl.InvalidateStyle();
PointMarkerImage = null;
PointMarkerEmptyImage = null;
PointMarkerHighlightImage = null;
}
#endregion
#region ClearEffectiveStyles
protected override void ClearEffectiveStyles()
{
_EffectiveChartSeriesStyle.InvalidateStyle();
_EffectiveDataLabelStyle.InvalidateStyle();
if (LegendItem != null)
LegendItem.EffectiveStyles.InvalidateStyles();
PointMarkerImage = null;
PointMarkerEmptyImage = null;
PointMarkerHighlightImage = null;
}
#endregion
#region StyleChanged
protected override void StyleChanged(object sender, PropertyChangedEventArgs e)
{
base.StyleChanged(sender, e);
if (sender is ChartLegendItemVisualStyles && LegendItem != null)
InvalidateRender(LegendItem.Bounds);
}
#endregion
#endregion
#region InvalidateRender
public override void InvalidateRender()
{
ChartXy chartXy = Parent as ChartXy;
if (chartXy != null)
chartXy.InvalidateRender();
}
#endregion
#region ILegendItem
#region CheckedInLegend
/// <summary>
/// Gets or sets whether the series is checked in the Legend.
/// </summary>
[DefaultValue(true), Category("Legend")]
[Description("Indicates whether the series is checked in the Legend.")]
public bool CheckedInLegend
{
get { return (TestState(States.CheckedInLegend)); }
set
{
if (value != CheckedInLegend)
{
SetState(States.CheckedInLegend, value);
if (IsQualitativeXValues || IsQualitativeYValues)
InvalidateLayout();
if (PointLabelDisplayMode != PointLabelDisplayMode.None)
InvalidatePointLabels();
if (LegendItem != null)
LegendItem.UpdateCheckState();
OnPropertyChangedEx("CheckedInLegend", VisualChangeType.Render);
}
}
}
#endregion
#region ShowCheckBoxInLegend
/// <summary>
/// Gets or sets whether a checkbox for the series is shown in the Legend.
/// </summary>
[DefaultValue(true), Category("Legend")]
[Description("Indicates whether a checkbox for the series is shown in the Legend.")]
public bool ShowCheckBoxInLegend
{
get { return (TestState(States.ShowCheckBoxInLegend)); }
set
{
if (value != ShowCheckBoxInLegend)
{
SetState(States.ShowCheckBoxInLegend, value);
OnPropertyChangedEx("ShowCheckBoxInLegend", VisualChangeType.Layout);
}
}
}
#endregion
#region ShowInLegend
/// <summary>
/// Gets or sets whether the series is shown in the Legend.
/// </summary>
[DefaultValue(true), Category("Legend")]
[Description("Indicates whether the series is shown in the Legend.")]
public bool ShowInLegend
{
get { return (TestState(States.ShowInLegend)); }
set
{
if (value != ShowInLegend)
{
SetState(States.ShowInLegend, value);
OnPropertyChangedEx("ShowInLegend", VisualChangeType.Layout);
}
}
}
#endregion
#region ShowInParentLegend
/// <summary>
/// Gets or sets whether the series is shown in parent Legend(s).
/// </summary>
[DefaultValue(true), Category("Legend")]
[Description("Indicates whether the series is shown in parent Legend(s).")]
public bool ShowInParentLegend
{
get { return (TestState(States.ShowInParentLegend)); }
set
{
if (value != ShowInParentLegend)
{
SetState(States.ShowInParentLegend, value);
OnPropertyChangedEx("ShowInParentLegend", VisualChangeType.Layout);
}
}
}
#endregion
#region ShowMarkerInLegend
/// <summary>
/// Gets or sets whether the series Marker is shown in the Legend.
/// </summary>
[DefaultValue(true), Category("Legend")]
[Description("Indicates whether the series Marker is shown in the Legend.")]
public bool ShowMarkerInLegend
{
get { return (TestState(States.ShowMarkerInLegend)); }
set
{
if (value != ShowMarkerInLegend)
{
SetState(States.ShowMarkerInLegend, value);
OnPropertyChangedEx("ShowMarkerInLegend", VisualChangeType.Layout);
}
}
}
#endregion
#region LegendItem
///<summary>
/// Gets the item's parent LegendItem.
///</summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("Indicates the item's parent LegendItem.")]
public ChartLegendItem LegendItem
{
get { return (_LegendItem); }
internal set
{
if (_LegendItem != null)
_LegendItem.Dispose();
_LegendItem = value;
}
}
#endregion
#region LegendText
///<summary>
/// Gets or sets the text to display in the legend.
///</summary>
[DefaultValue(null), Category("Legend")]
[Description("Indicates the text to display in the legend.")]
public string LegendText
{
get { return (_LegendText); }
set
{
if (value != _LegendText)
{
_LegendText = value;
OnPropertyChangedEx("LegendText", Style.VisualChangeType.Layout);
}
}
}
#endregion
#region GetLegendItem
public ChartLegendItem GetLegendItem()
{
LegendItem = null;
if (ShowInLegend == true)
{
ChartXy chartXy = Parent as ChartXy;
LegendItem = new ChartLegendItem();
if (CheckedInLegend == true)
_LegendItem.CheckState = CheckState.Checked;
_LegendItem.Parent = chartXy.Legend;
_LegendItem.Name = Name;
_LegendItem.ItemText = LegendText;
if (string.IsNullOrEmpty(_LegendItem.Name) == true)
_LegendItem.Name = "(Series)";
_LegendItem.ChartItems.Add(this);
}
return (_LegendItem);
}
#endregion
#region GetLegendItems
public List<ChartLegendItem> GetLegendItems()
{
List<ChartLegendItem> list = new List<ChartLegendItem>();
ChartLegendItem item = GetLegendItem();
if (item != null)
list.Add(item);
foreach (ChartIndicator ci in ChartIndicators)
{
if (ci.Visible == true)
{
ChartLegendItem li = ci.GetLegendItem();
if (li != null)
list.Add(li);
}
}
return (list);
}
#endregion
#region GetLegendItemColor
public Color GetLegendItemColor()
{
ChartXy chartXy = Parent as ChartXy;
ChartLegendItemVisualStyle lstyle = ChartLegendItemVisualStyles[StyleType.Default];
if (lstyle.TextColor.IsEmpty == false)
return (lstyle.TextColor);
Color color = Color.Empty;
ChartSeriesVisualStyle sstyle = EffectiveChartSeriesStyle;
if (sstyle.ItemColor.IsEmpty == false)
return (sstyle.ItemColor);
PointMarkerVisualStyle pstyle = sstyle.MarkerVisualStyle;
switch (SeriesType)
{
case SeriesType.Bubble:
case SeriesType.Point:
case SeriesType.HorizontalDot:
case SeriesType.VerticalDot:
color = pstyle.Background.Color1;
break;
case SeriesType.Line:
ChartLineDisplayMode mode = GetLineDisplayMode(chartXy);
if ((mode & ChartLineDisplayMode.DisplayLine) == ChartLineDisplayMode.DisplayLine)
color = sstyle.LineStyle.LineColor;
else if ((mode & ChartLineDisplayMode.DisplaySpline) == ChartLineDisplayMode.DisplaySpline)
color = sstyle.SplineStyle.LineColor;
else if ((mode & ChartLineDisplayMode.DisplayStepLine) == ChartLineDisplayMode.DisplayStepLine)
color = sstyle.StepLineStyle.LineColor;
if (color.IsEmpty == true)
color = pstyle.Background.Color1;
break;
case SeriesType.HorizontalBar:
case SeriesType.VerticalBar:
ChartBarVisualStyle bstyle = sstyle.BarVisualStyle;
color = bstyle.Background.Color1;
break;
case SeriesType.HorizontalHiLoBar:
case SeriesType.VerticalHiLoBar:
HiLoBarSegmentStyle hstyle = sstyle.HiLoBarVisualStyle.DefaultSegmentStyle;
if (HiLoBarType == HiLoBarType.Line)
{
color = hstyle.Default.LineColor;
if (color.IsEmpty == true)
color = hstyle.CenterLine.LineColor;
}
else
{
color = hstyle.BoxBackground.Color1;
}
break;
}
if (color.IsEmpty == true)
color = _DefaultPaletteColor;
return (color);
}
#endregion
#region RenderLegendItemMarker
public void RenderLegendItemMarker(Graphics g,
ChartLegendItem litem, ChartLegendItemVisualStyle style)
{
ChartXy chartXy = Parent as ChartXy;
ChartSeriesVisualStyle sstyle = EffectiveChartSeriesStyle;
Rectangle bounds = litem.MarkerBounds;
SmoothingMode sm = g.SmoothingMode;
g.SmoothingMode = SmoothingMode.AntiAlias;
switch (SeriesType)
{
case SeriesType.HorizontalHiLoBar:
case SeriesType.VerticalHiLoBar:
RenderHiLoBarMarker(g, bounds, chartXy, sstyle);
break;
case SeriesType.VerticalBar:
case SeriesType.HorizontalBar:
RenderBarMarker(g, bounds, chartXy, sstyle);
break;
case SeriesType.Bubble:
RenderBubbleMarker(g, bounds, chartXy, sstyle);
break;;
case SeriesType.VerticalDot:
case SeriesType.HorizontalDot:
case SeriesType.Point:
RenderDotMarker(g, bounds, chartXy, sstyle);
break;
case SeriesType.Line:
RenderLineMarker(g, bounds, chartXy, sstyle);
break;
default:
RenderDefaultMarker(g, bounds, sstyle);
break;
}
g.SmoothingMode = sm;
}
#region RenderHiLoBarMarker
private void RenderHiLoBarMarker(Graphics g,
Rectangle bounds, ChartXy chartXy, ChartSeriesVisualStyle sstyle)
{
Rectangle r = bounds;
r.Inflate(-1, -1);
if (r.Width > 0 && r.Height > 0)
{
SmoothingMode sm = g.SmoothingMode;
g.SmoothingMode = SmoothingMode.None;
HiLoBarSegmentStyle hstyle = sstyle.HiLoBarVisualStyle.DefaultSegmentStyle;
if (HiLoBarType == HiLoBarType.Line)
{
Color color = hstyle.Default.LineColor;
if (color.IsEmpty == true)
color = hstyle.CenterLine.LineColor;
if (color.IsEmpty == true)
color = _DefaultPaletteColor;
if (color.IsEmpty == true)
color = Color.Black;
if (IsRotated == true || r.Width > r.Height)
RenderHiLoHBarMarker(g, r, color);
else
RenderHiLoVBarMarker(g, r, color);
}
else
{
Background bk = hstyle.BoxBackground;
ChartLineVisualStyle lstyle = hstyle.BoxBorder;
if (IsRotated == true || r.Width > r.Height)
RenderHBoxMarker(g, r, bk, hstyle, lstyle);
else
RenderVBoxMarker(g, r, bk, hstyle, lstyle);
}
g.SmoothingMode = sm;
}
}
#region RenderHBoxMarker
private void RenderHBoxMarker(Graphics g, Rectangle r,
Background bk, HiLoBarSegmentStyle hstyle, ChartLineVisualStyle lstyle)
{
int n = r.Height / 4;
Rectangle t = r;
t.Inflate(-n, -n);
if (t.Height % 2 != 0)
{
t.Y--;
t.Height++;
}
using (Brush br = bk.GetBrush(t))
g.FillRectangle(br, t);
Color lineColor = lstyle.LineColor;
if (lineColor.IsEmpty == true)
lineColor = hstyle.Default.LineColor;
if (lineColor.IsEmpty == true)
lineColor = Color.Black;
using (Pen pen = new Pen(lineColor))
{
Point pt1 = new Point(r.X, (r.Y + r.Bottom) / 2);
Point pt2 = new Point(t.X, pt1.Y);
g.DrawLine(pen, pt1, pt2);
pt1.X = t.Right;
pt2.X = r.Right;
g.DrawLine(pen, pt1, pt2);
}
using (Pen pen = new Pen(lineColor))
g.DrawRectangle(pen, t);
}
#endregion
#region RenderVBoxMarker
private void RenderVBoxMarker(Graphics g, Rectangle r,
Background bk, HiLoBarSegmentStyle hstyle, ChartLineVisualStyle lstyle)
{
int n = r.Width / 4;
Rectangle t = r;
t.Inflate(-n, -n);
if (t.Width % 2 != 0)
{
t.X--;
t.Width++;
}
using (Brush br = bk.GetBrush(t))
g.FillRectangle(br, t);
Color lineColor = lstyle.LineColor;
if (lineColor.IsEmpty == true)
lineColor = hstyle.Default.LineColor;
if (lineColor.IsEmpty == true)
lineColor = Color.Black;
using (Pen pen = new Pen(lineColor))
{
Point pt1 = new Point((r.X + r.Right) / 2, r.Y);
Point pt2 = new Point(pt1.X, t.Y);
g.DrawLine(pen, pt1, pt2);
pt1.Y = t.Bottom;
pt2.Y = r.Bottom;
g.DrawLine(pen, pt1, pt2);
}
using (Pen pen = new Pen(lineColor))
g.DrawRectangle(pen, t);
}
#endregion
#region RenderHiLoHBarMarker
private void RenderHiLoHBarMarker(Graphics g, Rectangle r, Color color)
{
Point pt1 = new Point(r.X, (r.Y + r.Bottom) / 2);
Point pt2 = new Point(r.Right, pt1.Y);
using (Pen pen = new Pen(color))
{
g.DrawLine(pen, pt1, pt2);
int n = (r.Bottom - r.Top) / 3;
pt1.X = r.X + (r.Width / 4);
pt1.Y -= n;
pt2.X = pt1.X;
g.DrawLine(pen, pt1, pt2);
pt1.X = r.X + (r.Width / 4) * 3;
pt1.Y += (2 * n);
pt2.X = pt1.X;
g.DrawLine(pen, pt1, pt2);
}
}
#endregion
#region RenderHiLoVBarMarker
private void RenderHiLoVBarMarker(Graphics g, Rectangle r, Color color)
{
Point pt1 = new Point((r.X + r.Right) / 2, r.Y);
Point pt2 = new Point(pt1.X, r.Bottom);
using (Pen pen = new Pen(color))
{
g.DrawLine(pen, pt1, pt2);
int n = (r.Right - r.Left) / 3;
pt1.X -= n;
pt1.Y = r.Y + (r.Height / 4);
pt2.Y = pt1.Y;
g.DrawLine(pen, pt1, pt2);
pt1.X += (2 * n);
pt1.Y = r.Y + (r.Height / 4) * 3;
pt2.Y = pt1.Y;
g.DrawLine(pen, pt1, pt2);
}
}
#endregion
#endregion
#region RenderBarMarker
private void RenderBarMarker(Graphics g, Rectangle bounds, ChartXy chartXy, ChartSeriesVisualStyle sstyle)
{
ChartLineVisualStyle cstyle = sstyle.BarVisualStyle.Border;
Background bk = sstyle.BarVisualStyle.Background;
Rectangle r = bounds;
r.Inflate(-1, -1);
using (Brush br = bk.GetBrush(r))
{
g.FillRectangle(br, r);
if (cstyle.LineColor.IsEmpty == false && cstyle.LinePattern != LinePattern.None)
{
using (Pen pen = new Pen(cstyle.LineColor, cstyle.LineWidth))
{
if (cstyle.LinePattern != LinePattern.NotSet)
pen.DashStyle = (DashStyle)cstyle.LinePattern;
g.DrawRectangle(pen, r);
}
}
}
}
#endregion
#region RenderBubbleMarker
private void RenderBubbleMarker(Graphics g,
Rectangle bounds, ChartXy chartXy, ChartSeriesVisualStyle sstyle)
{
PointMarkerVisualStyle pstyle = sstyle.MarkerVisualStyle;
Background bk = pstyle.Background;
Rectangle r = bounds;
r.Inflate(-1, -1);
using (Brush br = pstyle.Background.GetBrush(r))
{
g.FillEllipse(br, r);
if (pstyle.BorderColor.IsEmpty == false && pstyle.BorderWidth > 0)
{
using (Pen pen = new Pen(pstyle.BorderColor, pstyle.BorderWidth))
g.DrawEllipse(pen, r);
}
}
}
#endregion
#region RenderDotMarker
private void RenderDotMarker(Graphics g,
Rectangle bounds, ChartXy chartXy, ChartSeriesVisualStyle sstyle)
{
PointMarkerVisualStyle pstyle = sstyle.MarkerVisualStyle;
Image marker = pstyle.GetPointMarkerImage();
if (marker != null)
{
g.DrawImage(marker, bounds);
}
else
{
marker = chartXy.GetPointMarker(g, pstyle.Type, pstyle.PointCount,
bounds.Size, pstyle.Rotation, pstyle.Background,
pstyle.BorderColor, pstyle.BorderWidth);
if (marker != null)
{
// Make allowances for the fact that GetPointMarker() adjusts the
// size and pos of the image to allow for better anti-aliasing
bounds.X--;
bounds.Y--;
g.DrawImageUnscaled(marker, bounds);
}
else
{
RenderDefaultMarker(g, bounds, sstyle);
}
}
}
#endregion
#region RenderLineMarker
private void RenderLineMarker(Graphics g,
Rectangle bounds, ChartXy chartXy, ChartSeriesVisualStyle sstyle)
{
ChartLineDisplayMode mode = GetLineDisplayMode(chartXy);
int n = bounds.Height / 2;
using (Pen pen = new Pen(GetLegendItemColor()))
{
g.DrawLine(pen,
new Point(bounds.X, bounds.Y + n),
new Point(bounds.Right - 1, bounds.Y + n));
}
if ((mode & ChartLineDisplayMode.DisplayPoints) == ChartLineDisplayMode.DisplayPoints)
{
n = Math.Min(bounds.Height, bounds.Width);
n = (int)Math.Ceiling((double)n / 2);
if (n % 2 == 0)
n++;
Rectangle r = bounds;
r.X += ((r.Width - n) / 2);
r.Y += ((r.Height - n) / 2);
r.Width = n;
r.Height = n;
PointMarkerVisualStyle pstyle = sstyle.MarkerVisualStyle;
Image marker2 = chartXy.GetPointMarker(g, pstyle.Type, pstyle.PointCount,
r.Size, 0, pstyle.Background, pstyle.BorderColor, pstyle.BorderWidth > 0 ? 1 : 0);
if (marker2 != null)
{
// Make allowances for the fact that GetPointMarker() adjusts the
// size and pos of the image to allow for better anti-aliasing
r.X--;
r.Y--;
g.DrawImageUnscaled(marker2, r);
}
else
{
RenderDefaultMarker(g, bounds, sstyle);
}
}
}
#endregion
#region RenderDefaultMarker
private void RenderDefaultMarker(Graphics g,
Rectangle bounds, ChartSeriesVisualStyle sstyle)
{
bounds.Width++;
bounds.Height++;
Background background = sstyle.MarkerVisualStyle.Background;
if (background.IsEmpty == true)
{
g.FillRectangle(Brushes.DimGray, bounds);
}
else
{
using (Brush br = background.GetBrush(bounds))
g.FillRectangle(br, bounds);
}
}
#endregion
#endregion
#endregion
#region Copy/CopyTo
public override ChartVisualElement Copy()
{
ChartSeries copy = new ChartSeries();
CopyTo(copy);
return (copy);
}
public override void CopyTo(ChartVisualElement copy)
{
ChartSeries c = copy as ChartSeries;
if (c != null)
{
base.CopyTo(c);
c.AxisX = AxisX;
c.AxisY = AxisY;
c.AreaBaseValue = AreaBaseValue;
c.BarFillRange = BarFillRange;
c.BarLabelPosition = BarLabelPosition;
c.BarShadingEnabled = BarShadingEnabled;
c.BarWidthRatio = BarWidthRatio;
c.BubbleIntensityMode = BubbleIntensityMode;
c.BubbleScaleFactor = BubbleScaleFactor;
c.BubbleSizeMode = BubbleSizeMode;
foreach (ChartIndicator ci in ChartIndicators)
c.ChartIndicators.Add((ChartIndicator)ci.Copy());
c.ChartLegendItemVisualStyles =
(_ChartLegendItemVisualStyles != null) ? ChartLegendItemVisualStyles.Copy() : null;
c.ChartLineAreaDisplayMode = ChartLineAreaDisplayMode;
c.ChartLineDisplayMode = ChartLineDisplayMode;
c.ChartSeriesVisualStyle =
(_ChartSeriesVisualStyle != null) ? ChartSeriesVisualStyle.Copy() : null;
c.ConvexHullDisplayMode = ConvexHullDisplayMode;
c.CrosshairEnabled = CrosshairEnabled;
c.CrosshairHighlightPoints = CrosshairHighlightPoints;
c.CrosshairShowLabels = CrosshairShowLabels;
foreach (DataLabel dl in DataLabels)
c.DataLabels.Add((DataLabel)dl.Copy());
c.DataLabelVisualStyle =
(_DataLabelVisualStyle != null) ? DataLabelVisualStyle.Copy() : null;
c.DataPropertyNameSeries = DataPropertyNameSeries;
c.DataPropertyNameX = DataPropertyNameX;
c.DataPropertyNamesY = DataPropertyNamesY;
c.DataMember = DataMember;
c.DataSource = DataSource;
c.DefaultPaletteColor = DefaultPaletteColor;
c.DisplayLinePointsOnTop = DisplayLinePointsOnTop;
c.DotPlotIndexValue = DotPlotIndexValue;
c.EmptyValues = EmptyValues;
c.EnableEmptyValues = EnableEmptyValues;
c.GroupId = GroupId;
c.PointLabelDisplayMode = PointLabelDisplayMode;
c.PointLabelMinDistance = PointLabelMinDistance;
c.PointLabelSkip = PointLabelSkip;
c.ScaleTypeX = ScaleTypeX;
c.ScaleTypeY = ScaleTypeY;
foreach (SeriesPoint sp in SeriesPoints)
c.SeriesPoints.Add(sp.Copy());
c.SeriesType = SeriesType;
c.ShowEmptyLines = ShowEmptyLines;
c.ShowEmptyPoints = ShowEmptyPoints;
c.ShowHiLoBarMedianLines = ShowHiLoBarMedianLines;
c.ShowOriginValueLabels = ShowOriginValueLabels;
c.StackQualitativePoints = StackQualitativePoints;
c.StepLines = StepLines;
c.StepLineMode = StepLineMode;
c.CheckedInLegend = CheckedInLegend;
c.LegendText = LegendText;
c.ShowCheckBoxInLegend = ShowCheckBoxInLegend;
c.ShowInLegend = ShowInLegend;
c.ShowInParentLegend = ShowInParentLegend;
c.ShowMarkerInLegend = ShowMarkerInLegend;
}
}
#endregion
#region GetSerialData
internal override SerialElementCollection GetSerialData(string serialName)
{
SerialElementCollection sec = new SerialElementCollection();
if (serialName != null)
{
if (serialName.Equals("") == true)
serialName = "ChartSeries";
sec.AddStartElement(serialName);
}
if (AxisX != null && string.IsNullOrEmpty(AxisX.Name) == false)
sec.AddValue("AxisX", AxisX.Name);
if (AxisY != null && string.IsNullOrEmpty(AxisY.Name) == false)
sec.AddValue("AxisY", AxisY.Name);
sec.AddDataValue("AreaBaseValue", AreaBaseValue, null);
sec.AddValue("BarFillRange", BarFillRange, BarFillRange.NotSet);
sec.AddValue("BarLabelPosition", BarLabelPosition, BarLabelPosition.NotSet);
sec.AddValue("BarShadingEnabled", BarShadingEnabled, Tbool.NotSet);
sec.AddValue("BarWidthRatio", BarWidthRatio, 0d);
sec.AddValue("BubbleIntensityMode", BubbleIntensityMode, BubbleIntensityMode.NotSet);
sec.AddValue("BubbleScaleFactor", BubbleScaleFactor, 1.0d);
sec.AddValue("BubbleSizeMode", BubbleSizeMode, BubbleSizeMode.NotSet);
if (_ChartIndicators != null && _ChartIndicators.Count > 0)
{
sec.AddStartElement("ChartIndicators count=\"" + _ChartIndicators.Count + "\"");
foreach (ChartIndicator ci in _ChartIndicators)
sec.AddElement(ci.GetSerialData(""));
sec.AddEndElement("ChartIndicators");
}
if (_ChartLegendItemVisualStyles != null)
sec.AddElement(_ChartLegendItemVisualStyles.GetSerialData("ChartLegendItemVisualStyles"));
sec.AddValue("ChartLineAreaDisplayMode", ChartLineAreaDisplayMode, ChartLineAreaDisplayMode.NotSet);
sec.AddValue("ChartLineDisplayMode", ChartLineDisplayMode, ChartLineDisplayMode.NotSet);
if (_ChartSeriesVisualStyle != null)
sec.AddElement(_ChartSeriesVisualStyle.GetSerialData("ChartSeriesVisualStyle"));
sec.AddValue("ConvexHullDisplayMode", ConvexHullDisplayMode, ConvexHullDisplayMode.NotSet);
sec.AddValue("CrosshairEnabled", CrosshairEnabled, Tbool.NotSet);
sec.AddValue("CrosshairHighlightPoints", CrosshairHighlightPoints, Tbool.NotSet);
sec.AddValue("CrosshairShowLabels", CrosshairShowLabels, Tbool.NotSet);
if (_DataLabels != null && _DataLabels.Count > 0)
{
sec.AddStartElement("DataLabels count=\"" + _DataLabels.Count + "\"");
foreach (DataLabel dl in _DataLabels)
sec.AddElement(dl.GetSerialData(""));
sec.AddEndElement("DataLabels");
}
if (_DataLabelVisualStyle != null)
sec.AddElement(_DataLabelVisualStyle.GetSerialData("DataLabelVisualStyle"));
//sec.AddDataValue("DataSource", DataSource, null);
sec.AddValue("DataMember", DataMember, null);
sec.AddValue("DataPropertyNameSeries", DataPropertyNameSeries, null);
sec.AddValue("DataPropertyNameX", DataPropertyNameX, null);
if (_DataPropertyNamesY != null && _DataPropertyNamesY.Count > 0)
{
sec.AddStartElement("DataPropertyNamesYs count=\"" + _DataPropertyNamesY.Count + "\"");
foreach (string s in _DataPropertyNamesY)
sec.AddValue("DataPropertyNamesY", s);
sec.AddEndElement("DataPropertyNamesYs");
}
sec.AddValue("DefaultPaletteColor", DefaultPaletteColor, Color.Empty);
sec.AddValue("DisplayLinePointsOnTop", DisplayLinePointsOnTop, true);
sec.AddValue("DotPlotIndexValue", DotPlotIndexValue, 1.0d);
if (_EmptyValues != null && _EmptyValues.Length > 0)
{
sec.AddStartElement("EmptyValues count=\"" + _EmptyValues.Length + "\"");
foreach (object value in _EmptyValues)
sec.AddValue("EmptyValue", value);
sec.AddEndElement("EmptyValues");
}
sec.AddValue("EnableEmptyValues", EnableEmptyValues, false);
sec.AddValue("GroupId", GroupId, 0);
sec.AddValue("HiLoBarType", HiLoBarType, HiLoBarType.Box);
sec.AddValue("PointLabelDisplayMode", PointLabelDisplayMode, PointLabelDisplayMode.NotSet);
sec.AddValue("PointLabelMinDistance", PointLabelMinDistance, 0);
sec.AddValue("PointLabelSkip", PointLabelSkip, 0);
sec.AddValue("ScaleTypeX", ScaleTypeX, ScaleType.NotSet);
sec.AddValue("ScaleTypeY", ScaleTypeY, ScaleType.NotSet);
if (_SeriesPoints != null && _SeriesPoints.Count > 0)
{
sec.AddStartElement("SeriesPoints count=\"" + _SeriesPoints.Count + "\"");
foreach (SeriesPoint sp in _SeriesPoints)
sec.AddElement(sp.GetSerialData());
sec.AddEndElement("SeriesPoints");
}
sec.AddValue("SeriesType", SeriesType, SeriesType.Point);
sec.AddValue("ShowEmptyLines", ShowEmptyLines, false);
sec.AddValue("ShowEmptyPoints", ShowEmptyPoints, false);
sec.AddValue("ShowHiLoBarMedianLines", ShowHiLoBarMedianLines, false);
sec.AddValue("ShowOriginValueLabels", ShowOriginValueLabels, true);
sec.AddValue("StackQualitativePoints", StackQualitativePoints, true);
sec.AddValue("StepLines", StepLines, StepLines.NotSet);
sec.AddValue("StepLineMode", StepLineMode, StepLineMode.NotSet);
sec.AddValue("CheckedInLegend", CheckedInLegend, true);
sec.AddValue("LegendText", LegendText, null);
sec.AddValue("ShowCheckBoxInLegend", ShowCheckBoxInLegend, true);
sec.AddValue("ShowInLegend", ShowInLegend, true);
sec.AddValue("ShowInParentLegend", ShowInParentLegend, true);
sec.AddValue("ShowMarkerInLegend", ShowMarkerInLegend, true);
sec.AddElement(base.GetSerialData(null));
if (serialName != null)
sec.AddEndElement(serialName);
return (sec);
}
#endregion
#region PutSerialData
#region ProcessValue
internal override void ProcessValue(SerialElement se)
{
ChartXy chartXy = Parent as ChartXy;
switch (se.Name)
{
case "AreaBaseValue":
AreaBaseValue = se.DataValue;
break;
case "AxisX":
if (chartXy != null)
AxisX = GetAncillaryAxis(chartXy.AncillaryAxesX, se.GetValueString());
break;
case "AxisY":
if (chartXy != null)
AxisY = GetAncillaryAxis(chartXy.AncillaryAxesY, se.GetValueString());
break;
case "BarFillRange":
BarFillRange = (BarFillRange)se.GetValueEnum(typeof(BarFillRange));
break;
case "BarLabelPosition":
BarLabelPosition = (BarLabelPosition)se.GetValueEnum(typeof(BarLabelPosition));
break;
case "BarShadingEnabled":
BarShadingEnabled = (Tbool)se.GetValueEnum(typeof(Tbool));
break;
case "BarWidthRatio":
BarWidthRatio = double.Parse(se.StringValue);
break;
case "BubbleIntensityMode":
BubbleIntensityMode = (BubbleIntensityMode)se.GetValueEnum(typeof(BubbleIntensityMode));
break;
case "BubbleScaleFactor":
BubbleScaleFactor = double.Parse(se.StringValue);
break;
case "BubbleSizeMode":
BubbleSizeMode = (BubbleSizeMode)se.GetValueEnum(typeof(BubbleSizeMode));
break;
case "ChartLineAreaDisplayMode":
ChartLineAreaDisplayMode = (ChartLineAreaDisplayMode)se.GetValueEnum(typeof(ChartLineAreaDisplayMode));
break;
case "ChartLineDisplayMode":
ChartLineDisplayMode = (ChartLineDisplayMode)se.GetValueEnum(typeof(ChartLineDisplayMode));
break;
case "CheckedInLegend":
CheckedInLegend = bool.Parse(se.StringValue);
break;
case "ConvexHullDisplayMode":
ConvexHullDisplayMode = (ConvexHullDisplayMode)se.GetValueEnum(typeof(ConvexHullDisplayMode));
break;
case "CrosshairEnabled":
CrosshairEnabled = (Tbool)se.GetValueEnum(typeof(Tbool));
break;
case "CrosshairHighlightPoints":
CrosshairHighlightPoints = (Tbool)se.GetValueEnum(typeof(Tbool));
break;
case "CrosshairShowLabels":
CrosshairShowLabels = (Tbool)se.GetValueEnum(typeof(Tbool));
break;
case "DataMember":
DataMember = se.StringValue;
break;
case "DataPropertyNameSeries":
DataPropertyNameSeries = se.StringValue;
break;
case "DataPropertyNameX":
DataPropertyNameX = se.StringValue;
break;
case "DataPropertyNamesY":
DataPropertyNamesY.Add(se.StringValue);
break;
case "DataSource":
DataSource = se.DataValue;
break;
case "DefaultPaletteColor":
DefaultPaletteColor = se.GetValueColor();
break;
case "DisplayLinePointsOnTop":
DisplayLinePointsOnTop = bool.Parse(se.StringValue);
break;
case "DotPlotIndexValue":
DotPlotIndexValue = double.Parse(se.StringValue);
break;
case "EmptyValues":
EmptyValues[se.ValueIndex] = se.DataValue;
break;
case "EnableEmptyValues":
EnableEmptyValues = bool.Parse(se.StringValue);
break;
case "GroupId":
GroupId = int.Parse(se.StringValue);
break;
case "HiLoBarType":
HiLoBarType = (HiLoBarType)se.GetValueEnum(typeof(HiLoBarType));
break;
case "LegendText":
LegendText = se.StringValue;
break;
case "PointLabelDisplayMode":
PointLabelDisplayMode = (PointLabelDisplayMode)se.GetValueEnum(typeof(PointLabelDisplayMode));
break;
case "PointLabelMinDistance":
PointLabelMinDistance = int.Parse(se.StringValue);
break;
case "PointLabelSkip":
PointLabelSkip = int.Parse(se.StringValue);
break;
case "ScaleTypeX":
ScaleTypeX = (ScaleType)se.GetValueEnum(typeof(ScaleType));
break;
case "ScaleTypeY":
ScaleTypeY = (ScaleType)se.GetValueEnum(typeof(ScaleType));
break;
case "SeriesType":
SeriesType = (SeriesType)se.GetValueEnum(typeof(SeriesType));
break;
case "ShowCheckBoxInLegend":
ShowCheckBoxInLegend = bool.Parse(se.StringValue);
break;
case "ShowEmptyLines":
ShowEmptyLines = bool.Parse(se.StringValue);
break;
case "ShowEmptyPoints":
ShowEmptyPoints = bool.Parse(se.StringValue);
break;
case "ShowHiLoBarMedianLines":
ShowHiLoBarMedianLines = bool.Parse(se.StringValue);
break;
case "ShowInLegend":
ShowInLegend = bool.Parse(se.StringValue);
break;
case "ShowInParentLegend":
ShowInParentLegend = bool.Parse(se.StringValue);
break;
case "ShowMarkerInLegend":
ShowMarkerInLegend = bool.Parse(se.StringValue);
break;
case "ShowOriginValueLabels":
ShowOriginValueLabels = bool.Parse(se.StringValue);
break;
case "StackQualitativePoints":
StackQualitativePoints = bool.Parse(se.StringValue);
break;
case "StepLines":
StepLines = (StepLines)se.GetValueEnum(typeof(StepLines));
break;
case "StepLineMode":
StepLineMode = (StepLineMode)se.GetValueEnum(typeof(StepLineMode));
break;
default:
base.ProcessValue(se);
break;
}
}
#region GetAncillaryAxis
private ChartAxis GetAncillaryAxis(ChartAxesCollection axes, string name)
{
foreach (ChartAxis axis in axes)
{
if (name.Equals(axis.Name) == true)
return (axis);
}
return (null);
}
#endregion
#endregion
#region ProcessCollection
internal override void ProcessCollection(SerialElement se)
{
SerialElementCollection sec = se.Sec;
switch (se.Name)
{
case "ChartIndicators":
sec.PutSerialData(this);
break;
case "ChartLegendItemVisualStyles":
sec.PutSerialData(ChartLegendItemVisualStyles);
break;
case "ChartSeriesVisualStyle":
sec.PutSerialData(ChartSeriesVisualStyle);
break;
case "DataLabel":
sec.PutSerialData(DataLabels[se.ValueIndex]);
break;
case "DataLabels":
sec.PutSerialData(this);
break;
case "DataLabelVisualStyle":
sec.PutSerialData(DataLabelVisualStyle);
break;
case "DataPropertyNamesYs":
if (se.ArrayCount > 0)
{
DataPropertyNamesY = new CustomCollection<string>(se.ArrayCount);
sec.PutSerialData(this);
}
break;
case "EmptyValues":
if (se.ArrayCount > 0)
{
EmptyValues = new object[se.ArrayCount];
sec.PutSerialData(this);
}
break;
case "RegressionLine":
string rname = se.Sec.GetItemValue("Name");
RegressionLine reg = ChartIndicators[rname] as RegressionLine;
if (reg != null)
ChartIndicators.Remove(reg);
reg = new RegressionLine(rname);
if (reg != null)
{
sec.PutSerialData(reg);
ChartIndicators.Add(reg);
}
break;
case "SeriesPoints":
if (se.ArrayCount > 0)
{
SeriesPoints = new SeriesPointCollection();
sec.PutSerialData(this);
}
break;
case "SeriesPoint":
SeriesPoint sp = new SeriesPoint();
sec.PutSerialData(sp);
SeriesPoints.Add(sp);
break;
case "TrendLine":
string tname = se.Sec.GetItemValue("Name");
TrendLine trend = ChartIndicators[tname] as TrendLine;
if (trend != null)
ChartIndicators.Remove(trend);
trend = new TrendLine(tname);
if (trend != null)
{
sec.PutSerialData(trend);
ChartIndicators.Add(trend);
}
break;
default:
base.ProcessCollection(se);
break;
}
}
#endregion
#endregion
#region Series States
[Flags]
private enum States : uint
{
FilterIgnoreMatchCase = (1U << 0),
CheckedInLegend = (1U << 1),
ShowInLegend = (1U << 2),
ShowInParentLegend = (1U << 3),
ShowCheckBoxInLegend = (1U << 4),
ShowMarkerInLegend = (1U << 5),
IsSorted = (1U << 6),
IsRotated = (1U << 7),
StackQualitativePoints = (1U << 8),
DisplayLinePointsOnTop = (1U << 9),
EnableEmptyValues = (1U << 10),
ShowEmptyLines = (1U << 11),
ShowEmptyPoints = (1U << 12),
ShowOriginValueLabels = (1U << 13),
ShowHiLoBarMedianLines = (1U << 14),
NeedToUpdateBindings = (1U << 15),
}
#region TestState
private bool TestState(States state)
{
return ((_States & state) == state);
}
#endregion
#region SetState
private void SetState(States state, bool value)
{
if (value == true)
_States |= state;
else
_States &= ~state;
}
#endregion
#endregion
#region IDisposable
public override void Dispose()
{
AxisX = null;
AxisY = null;
ChartIndicators = null;
ChartLegendItemVisualStyles = null;
ChartSeriesVisualStyle = null;
DataLabels = null;
DataLabelVisualStyle = null;
SeriesPoints = null;
base.Dispose();
}
#endregion
}
#region SortedSeriesPoints
public class SortedSeriesPoints
{
#region Private variables
private ChartSeries _ChartSeries;
private SeriesPointCollection _Spc;
private int[] _IndexArray;
private int[] _CountArray;
private int _SeriesLayoutCount;
private int _FirstDisplayIndex = -1;
private int _LastDisplayIndex = -1;
private double _Slope = double.NaN;
private double _Intercept = double.NaN;
private bool _SlopeCalculated;
private int _SlopeIndex;
#endregion
public SortedSeriesPoints(ChartSeries series, bool sortPoints)
{
_ChartSeries = series;
_Spc = series.SeriesPoints;
if (sortPoints == true)
_IndexArray = CreateIndexArray(_Spc);
}
#region Public properties
#region Count
public int Count
{
get
{
if (_IndexArray != null)
return (_IndexArray.Length);
return (_Spc.Count);
}
}
#endregion
#region Indexer[int]
public SeriesPoint this[int index]
{
get
{
if (_IndexArray != null)
index = _IndexArray[index];
return (_Spc[index]);
}
}
#endregion
#region IsSorted
public bool IsSorted
{
get { return (_ChartSeries.IsSorted); }
}
#endregion
#region SeriesLayoutCount
public int SeriesLayoutCount
{
get { return (_SeriesLayoutCount); }
set
{
if (value != _SeriesLayoutCount)
{
_SeriesLayoutCount = value;
_FirstDisplayIndex = -1;
_LastDisplayIndex = -1;
}
}
}
#endregion
#endregion
#region Internal properties
#region CountArray
internal int[] CountArray
{
get { return (_CountArray); }
set { _CountArray = value; }
}
#endregion
#region IndexArray
internal int[] IndexArray
{
get { return (_IndexArray); }
set { _IndexArray = value; }
}
#endregion
#region Intercept
internal double Intercept
{
get
{
if (_SlopeCalculated == false)
CalcSeriesSlope();
return (_Intercept);
}
set { _Intercept = value; }
}
#endregion
#region Slope
internal double Slope
{
get
{
if (_SlopeCalculated == false)
CalcSeriesSlope();
return (_Slope);
}
set { _Slope = value; }
}
#endregion
#region SlopeIndex
internal int SlopeIndex
{
get { return (_SlopeIndex); }
set
{
if (_SlopeIndex != value)
{
_SlopeIndex = value;
_SlopeCalculated = false;
}
}
}
#endregion
#endregion
#region CreateIndexArray
private int[] CreateIndexArray(SeriesPointCollection spc)
{
int[] indexArray = new int[_Spc.Count];
object[] keyArray = new object[_Spc.Count];
for (int i = 0; i < _Spc.Count; i++)
{
indexArray[i] = i;
keyArray[i] = _Spc[i].ValueX;
}
Array.Sort(keyArray, indexArray);
return (indexArray);
}
#endregion
#region SearchX
public int SearchX(object okey)
{
ChartXy chartXy = _ChartSeries.Parent as ChartXy;
if (IsSorted == true)
{
int min = 0;
int max = Count - 1;
while (min <= max)
{
int mid = (min + max) / 2;
int cmp = chartXy.DataCompare(okey, this[mid].ValueX);
if (cmp > 0)
min = mid + 1;
else if (cmp < 0)
max = mid - 1;
else
return (mid);
}
return (-((min > 0) ? min - 1 : 0));
}
else
{
for (int i = 0; i < Count; i++)
{
if (chartXy.DataCompare(okey, this[i].ValueX) == 0)
return (i);
}
return (-1);
}
}
#endregion
#region SearchY
public int SearchY(object okey)
{
ChartXy chartXy = _ChartSeries.Parent as ChartXy;
for (int i = 0; i < _Spc.Count; i++)
{
if (_Spc[i].ValueY[0].Equals(okey))
return (i);
}
return (0);
}
#endregion
#region GetQualitativeXIndex
internal int GetQualitativeXIndex(object okey)
{
int index;
if (okey is string)
index = _ChartSeries.QualitativeXValues.IndexOf((string)okey);
else
index = Convert.ToInt32(okey);
return (index);
}
#endregion
#region GetQualitativeYIndex
internal int GetQualitativeYIndex(object okey)
{
int index;
if (okey is string)
index = _ChartSeries.QualitativeYValues.IndexOf((string)okey);
else
index = Convert.ToInt32(okey);
return (index);
}
#endregion
#region CalcSeriesSlope
private void CalcSeriesSlope()
{
ChartXy chartXy = _ChartSeries.Parent as ChartXy;
if (chartXy != null)
{
ChartAxis axisX = _ChartSeries.AxisX ?? chartXy.AxisX;
ChartAxis axisY = _ChartSeries.AxisY ?? chartXy.AxisY;
if (_ChartSeries.ActualScaleTypeX != ScaleType.NotSet)
{
int n = Count;
double sumX = 0;
double sumY = 0;
double sumXx = 0;
double sumXy = 0;
int nn = 0;
for (int i = 0; i < n; i++)
{
SeriesPoint sp = this[i];
if (sp.IsEmpty == false && (sp.ValueY.Length > _SlopeIndex))
{
nn++;
double x;
switch (_ChartSeries.ActualScaleTypeX)
{
case ScaleType.DateTime:
x = chartXy.GetDateTimePointValue(axisX,
axisX.TickmarkLayout, (DateTime)sp.ValueX, (DateTime)_ChartSeries.MinValueX);
break;
case ScaleType.Qualitative:
x = _ChartSeries.QualitativeXValues.IndexOf(sp.ValueX);
break;
default:
x = Convert.ToDouble(sp.ValueX);
break;
}
double y;
switch (_ChartSeries.ActualScaleTypeY)
{
case ScaleType.DateTime:
y = chartXy.GetDateTimePointValue(axisY, axisY.TickmarkLayout, (DateTime)sp.ValueY[_SlopeIndex]);
break;
case ScaleType.Qualitative:
y = _ChartSeries.QualitativeYValues.IndexOf(sp.ValueY[_SlopeIndex]);
break;
default:
y = Convert.ToDouble(sp.ValueY[_SlopeIndex]);
break;
}
sumX += x;
sumY += y;
sumXx += (x * x);
sumXy += (x * y);
}
}
double a = nn * sumXy;
double b = sumX * sumY;
double c = nn * sumXx;
double d = sumX * sumX;
double m = (a - b) / (c - d);
double yi = (sumY - (m * sumX)) / nn;
Slope = m;
Intercept = yi;
_SlopeCalculated = true;
}
}
}
#endregion
#region GetSeriesPoint
internal SeriesPoint GetSeriesPoint(object key)
{
if (Count > 0)
{
int index;
if (this[0].IsQuantitativeXValue == true)
index = SearchX(key);
else
index = GetQualitativeXIndex(key) - 1;
if (index < 0 && IsSorted == true)
index = -index;
if ((uint)index < Count)
return (this[index]);
}
return (null);
}
#endregion
}
#endregion
#region PointData
public class PointData
{
public List<Point[]> Points;
public List<SeriesPoint[]> SeriesPoints;
}
#endregion
#region BubblePlotData
internal class BubblePlotData
{
public double MinSize;
public double MaxSize;
public double TotalSize;
public double MinIntensity;
public double MaxIntensity;
public void Clear()
{
MinSize = double.MaxValue;
MaxSize = double.MinValue;
MinIntensity = double.MaxValue;
MaxIntensity = double.MinValue;
TotalSize = 0;
}
}
#endregion
#region BarRenderData
internal class BarRenderData
{
public ChartAxis Axis;
public ChartXy ChartXy;
public BarFillRange FillRange;
public bool BarShading;
public Point Spt;
public SeriesPoint Sp;
public ChartSeriesVisualStyle SeriesStyle;
public BarRenderData(ChartXy chartXy, ChartAxis axis)
{
ChartXy = chartXy;
Axis = axis;
}
}
#endregion
#region HiLoRenderData
public class HiLoRenderData
{
#region Private variables
private ChartAxis _Axis;
private ChartXy _ChartXy;
private Point _Spt;
private SeriesPoint _Sp;
private int _Index;
private ChartSeriesVisualStyle _SeriesStyle;
private int[] _Value;
private bool _IsAlternate;
private int _EndDelta;
#endregion
public HiLoRenderData(ChartXy chartXy, ChartAxis axis)
{
_ChartXy = chartXy;
_Axis = axis;
}
#region Public properties
#region AlternateStyle
/// <summary>
/// Gets the alternate segment style used when Open/Close values are reversed.
/// </summary>
public HiLoBarSegmentStyle AlternateStyle
{
get { return (SeriesStyle.HiLoBarVisualStyle.AlternateSegmentStyle); }
}
#endregion
#region DefaultStyle
/// <summary>
/// Gets the default segment style used when Open/Close values are not reversed.
/// </summary>
public HiLoBarSegmentStyle DefaultStyle
{
get { return (SeriesStyle.HiLoBarVisualStyle.DefaultSegmentStyle); }
}
#endregion
#region IsAlternate
/// <summary>
/// Gets whether the segment is to be render as 'Alternate'.
/// </summary>
public bool IsAlternate
{
get { return (_IsAlternate); }
internal set { _IsAlternate = value; }
}
#endregion
#region SeriesStyle
/// <summary>
/// Gets the associated series visual style.
/// </summary>
public ChartSeriesVisualStyle SeriesStyle
{
get { return (_SeriesStyle); }
internal set { _SeriesStyle = value; }
}
#endregion
#region Value
/// <summary>
/// Gets an array of specified HiLo coordinate data values (x or y,
/// depending upon the bar orientation). The values are specified
/// in [High=0, Low=1, Close=2, Open=3, Median=4] order, followed
/// by any 'extra' user supplied bar values.
/// </summary>
public int[] Value
{
get { return (_Value); }
internal set { _Value = value; }
}
#endregion
#endregion
#region Internal properties
#region Axis
internal ChartAxis Axis
{
get { return (_Axis); }
set { _Axis = value; }
}
#endregion
#region ChartXy
internal ChartXy ChartXy
{
get { return (_ChartXy); }
set { _ChartXy = value; }
}
#endregion
#region EndDelta
public int EndDelta
{
get { return (_EndDelta); }
set { _EndDelta = value; }
}
#endregion
#region Index
internal int Index
{
get { return (_Index); }
set { _Index = value; }
}
#endregion
#region Sp
internal SeriesPoint Sp
{
get { return (_Sp); }
set { _Sp = value; }
}
#endregion
#region Spt
internal Point Spt
{
get { return (_Spt); }
set { _Spt = value; }
}
#endregion
#endregion
}
#endregion
#region AMath (approximate math)
internal class AMath
{
public static double ToScalar(double x)
{
return (AMath.Sqrt((float)(x / Math.PI)) * 2);
}
public static float Sqrt(float x)
{
if (x != 0)
{
FloatIntUnion u;
u.tmp = 0;
u.f = x;
u.tmp -= 1 << 23; // Subtract 2^m
u.tmp >>= 1; // Divide by 2
u.tmp += 1 << 29; // Add ((b + 1) / 2) * 2^m
return (u.f);
}
return (0);
}
[StructLayout(LayoutKind.Explicit)]
private struct FloatIntUnion
{
[FieldOffset(0)]
public float f;
[FieldOffset(0)]
public int tmp;
}
}
#endregion
#region enums
#region BarLabelPosition
/// <summary>
/// Specifies the position for Bar series labels.
/// </summary>
public enum BarLabelPosition
{
/// <summary>
/// Not set (default is Center).
/// </summary>
NotSet = -1,
/// <summary>
/// Labels will be positioned in the center of the bar.
/// </summary>
Center,
/// <summary>
/// Labels will be positioned outside the bar, relative to its origin.
/// </summary>
Near,
/// <summary>
/// Labels will be positioned inside the bar, relative to its origin.
/// </summary>
NearInside,
/// <summary>
/// Labels will be positioned outside the bar, opposite to its origin.
/// </summary>
Far,
/// <summary>
/// Labels will be positioned inside the bar, opposite to its origin.
/// </summary>
FarInside,
}
#endregion
#region BarSegment
public enum BarSegment
{
/// <summary>
/// Top portion of Vertical bar (full area).
/// </summary>
Top,
/// <summary>
/// Partial Top area of Vertical bar.
/// </summary>
TopPartial,
/// <summary>
/// Bottom portion of Vertical bar (full area).
/// </summary>
Bottom,
/// <summary>
/// Partial Bottom area of Vertical bar.
/// </summary>
BottomPartial,
/// <summary>
/// Left portion of Horizontal bar (full area).
/// </summary>
Left,
/// <summary>
/// Partial Left area of Horizontal bar.
/// </summary>
LeftPartial,
/// <summary>
/// Right portion of Horizontal bar (full area).
/// </summary>
Right,
/// <summary>
/// Partial Right area of Horizontal bar.
/// </summary>
RightPartial,
}
#endregion
#region SeriesType
/// <summary>
/// Defines available Series types
/// </summary>
public enum SeriesType
{
Bubble,
HorizontalBar,
VerticalBar,
Line,
Point,
HorizontalDot, // Wilkinson dotplot
VerticalDot,
HorizontalHiLoBar, // Box, Candle, HiLo
VerticalHiLoBar,
//Bullet,
//Pie,
//Polar,
//Radar,
//TreeMap,
}
#endregion
#region ConvexHullDisplayMode
/// <summary>
/// Specifies the ConvexHull display mode
/// </summary>
[Flags]
public enum ConvexHullDisplayMode
{
/// <summary>
/// Not set (default is None).
/// </summary>
NotSet = 0,
/// <summary>
/// No Convex Hull processing will take place.
/// </summary>
None = (1 << 0),
/// <summary>
/// Convex Hull border will be displayed.
/// </summary>
DisplayBorder = (1 << 1),
/// <summary>
/// Convex Hull background area will be displayed.
/// </summary>
DisplayBackground = (1 << 2),
}
#endregion
#region PointLabelDisplayMode
/// <summary>
/// Specifies which PointLabels are to be displayed
/// </summary>
[Flags]
public enum PointLabelDisplayMode
{
/// <summary>
/// Not set (default is None).
/// </summary>
NotSet,
/// <summary>
/// No labels will be displayed.
/// </summary>
None = (1 << 0),
/// <summary>
/// All series points will display a label.
/// </summary>
AllSeriesPoints = (1 << 1),
/// <summary>
/// User defined DataLabels will be displayed.
/// </summary>
DataLabels = (1 << 2),
/// <summary>
/// Minimum 'X' Value label will be displayed.
/// </summary>
MinValueX = (1 << 3),
/// <summary>
/// Minimum 'Y' Value label will be displayed.
/// </summary>
MinValueY = (1 << 4),
/// <summary>
/// Maximum 'X' Value label will be displayed.
/// </summary>
MaxValueX = (1 << 5),
/// <summary>
/// Maximum 'Y' Value label will be displayed.
/// </summary>
MaxValueY = (1 << 6),
}
#endregion
#region StepLineMode
/// <summary>
/// Specifies the mode used to render "Step Lines" in
/// a given Line series.
/// </summary>
public enum StepLineMode
{
/// <summary>
/// Not set (default is HorizontalThenVertical).
/// </summary>
NotSet = -1,
/// <summary>
/// No Step Lines will be rendered.
/// </summary>
None,
/// <summary>
/// Step lines will be displayed between consecutive
/// series points, by first displaying the horizontal step
/// line, followed by the connecting vertical step line.
/// </summary>
HorizontalThenVertical,
/// <summary>
/// Step lines will be displayed between consecutive
/// series points, by first displaying the vertical step
/// line, followed by the connecting horizontal step line.
/// </summary>
VerticalThenHorizontal,
/// <summary>
/// Step lines will be displayed between consecutive
/// series points, by first displaying the midPoint horizontal
/// step line, followed by the connecting vertical step line.
/// </summary>
MidPoint,
}
#endregion
#region StepLines
/// <summary>
/// Specifies the mode used to render "Stepped Lines" in
/// a given Line series.
/// </summary>
public enum StepLines
{
/// <summary>
/// Not set (default is StepHv).
/// </summary>
NotSet = -1,
/// <summary>
/// No step lines will be displayed.
/// </summary>
None,
/// <summary>
/// Horizontal step lines will be displayed.
/// </summary>
Horizontal,
/// <summary>
/// Vertical step lines will be displayed.
/// </summary>
Vertical,
/// <summary>
/// Both horizontal and vertical step lines will be displayed.
/// </summary>
Both,
}
#endregion
#region ScaleType
/// <summary>
/// Specifies the scale type for the series points
/// </summary>
public enum ScaleType
{
/// <summary>
/// ScaleType is NotSet (default is 'Auto').
/// </summary>
NotSet,
/// <summary>
/// ScaleType is Automatic. Scale type will be determined
/// by the underlying, assigned data.
/// </summary>
Auto,
/// <summary>
/// DateTime data scale. Points will be treated as
/// DateTime values and will be shown as such on the axis.
/// </summary>
DateTime,
/// <summary>
/// Numerical data scale. Points will be treated as
/// numerical values and will be shown on the axis as numbers.
/// </summary>
Quantitative,
/// <summary>
/// Qualitative data scale. Points will be treated as
/// qualitative values and will be shown on the axis as text.
/// </summary>
Qualitative,
}
#endregion
#region HiLoBarType
/// <summary>
/// Specifies the HiloBar series display type.
/// </summary>
public enum HiLoBarType
{
/// <summary>
/// Box Plot display. Display is identical to 'Candle' except:
/// 1. Median separated segments are separately rendered using both
/// default and alternate box backgrounds.
/// 2. UseAlternateSegmentStyle defaults to false.
/// </summary>
Box,
/// <summary>
/// Candle Plot display. Display is identical to 'Box' except:
/// 1. Mmedian separated segments are both rendered using either
/// the default or alternate box background.
/// 2. UseAlternateSegmentStyle defaults to true.
/// </summary>
Candle,
/// <summary>
/// Line plot display.
/// </summary>
Line,
}
#endregion
#region HiLoBarSegment
public enum HiLoBarSegment
{
/// <summary>
/// Box (Box plot).
/// </summary>
Box,
/// <summary>
/// High whisker (Box, Candle, Line).
/// </summary>
HighWhisker,
/// <summary>
/// High whisker cap (Box, Candle, Line).
/// </summary>
HighWhiskerCap,
/// <summary>
/// Low whisker (Box, Candle, Line).
/// </summary>
LowWhisker,
/// <summary>
/// Low whisker cap (Box, Candle, Line).
/// </summary>
LowWhiskerCap,
/// <summary>
/// Open whisker (Line plot).
/// </summary>
OpenWhisker,
/// <summary>
/// Close whisker (Line Plot).
/// </summary>
CloseWhisker,
/// <summary>
/// Center line (Line plot).
/// </summary>
CenterLine,
/// <summary>
/// Full range (Line plot).
/// </summary>
FullRange,
/// <summary>
/// Median line (Box, Candle, Line).
/// </summary>
MedianLine,
/// <summary>
/// Bar shading (Box, Candle).
/// </summary>
BarShading,
}
#endregion
#endregion
#region AxisTypeConverter
///<summary>
/// AxisTypeConverter
///</summary>
public class AxisTypeConverter : TypeConverter
{
///<summary>
/// ConvertTo
///</summary>
///<param name="context"></param>
///<param name="culture"></param>
///<param name="value"></param>
///<param name="destinationType"></param>
///<returns></returns>
public override object ConvertTo(
ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
{
ChartAxis axis = value as ChartAxis;
if (axis != null)
{
if (string.IsNullOrEmpty(axis.Name) == false)
return (axis.Name);
return ("No Axis Name");
}
}
return (base.ConvertTo(context, culture, value, destinationType));
}
}
#endregion
}