5682 lines
164 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

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

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using DevComponents.DotNetBar.Charts.Style;
namespace DevComponents.DotNetBar.Charts
{
[Editor("DevComponents.Charts.Design.PieSeriesPointCollectionEditor, DevComponents.Charts.Design, " +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public class PieSeriesPointCollection : CustomNamedCollection<PieSeriesPoint>
{
#region Private variables
private ISeriesPointContainer _Parent;
private PieSeriesPointCollection _PieSlices;
private PieSeriesPointCollection _OtherSlices;
private PieSeriesPoint _OtherSlicePsp;
private double _PieTotal;
private double _PieMinExtent;
private double _PieMaxExtent;
private double _PieOuterExtent;
private double _PieTotalExtent;
private double _PieAverage;
private double _PieAverageExtent;
private PieRing _PieRing;
private States _States;
#endregion
#region Public properties
#region IsOther
/// <summary>
/// Gets whether the PieSeriesPoint is the 'Other' slice collection.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool IsOther
{
get { return (TestState(States.Other)); }
internal set { SetState(States.Other, value); }
}
#endregion
#region OtherSlicePsp
/// <summary>
/// Gets the 'Other' slice PieSeriesPoint.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public PieSeriesPoint OtherSlicePsp
{
get
{
if (_OtherSlicePsp == null)
_OtherSlicePsp = new PieSeriesPoint("Other", null, null);
return (_OtherSlicePsp);
}
}
#endregion
#region OtherSlices
/// <summary>
/// Gets the 'Other' slice collection of SeriesPoints.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public PieSeriesPointCollection OtherSlices
{
get { return (_OtherSlices); }
internal set { _OtherSlices = value; }
}
#endregion
#region Parent
/// <summary>
/// Gets the parent of this item.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public ISeriesPointContainer Parent
{
get { return (_Parent); }
internal set { _Parent = value; }
}
#endregion
#region PieAverage
/// <summary>
/// Gets the average pie point 'value' (Y[0]) for the collection.
/// </summary>
/// <returns></returns>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public double PieAverage
{
get { return (_PieAverage); }
internal set { _PieAverage = value; }
}
#endregion
#region PieAverageExtent
/// <summary>
/// Gets the average extent for the collection.
/// </summary>
/// <returns></returns>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public double PieAverageExtent
{
get { return (_PieAverageExtent); }
internal set { _PieAverageExtent = value; }
}
#endregion
#region PieSlices
/// <summary>
/// Gets the collection of displayed Pie slices.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public PieSeriesPointCollection PieSlices
{
get { return (_PieSlices); }
internal set
{
if (_PieSlices != null)
SetOtherHandler(false);
_PieSlices = value;
if (_PieSlices != null)
SetOtherHandler(true);
}
}
#region SetOtherHandler
private void SetOtherHandler(bool notify)
{
PieSeriesPointCollection spc = _PieSlices;
foreach (PieSeriesPoint psp in spc)
{
if (psp.IsOther == true)
{
SetPointNotify(psp, notify);
break;
}
}
}
#region SetPointNotify
private void SetPointNotify(PieSeriesPoint psp, bool notify)
{
if (notify == true)
{
psp.Parent = this;
psp.PropertyChanged += Sp_PropertyChanged;
}
else
{
psp.Parent = null;
psp.PropertyChanged -= Sp_PropertyChanged;
}
}
#endregion
#region Sp_PropertyChanged
void Sp_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
VisualPropertyChangedEventArgs vce = e as VisualPropertyChangedEventArgs;
if (vce != null)
{
PieSeriesPoint psp = sender as PieSeriesPoint;
if (psp != null)
psp.NotifyVisualParent(psp, vce.ChangeType);
}
}
#endregion
#endregion
#endregion
#region PieTotal
/// <summary>
/// Gets the sum total of the pie collection 'values' (Y[0]).
/// </summary>
/// <returns></returns>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public double PieTotal
{
get { return (_PieTotal); }
internal set { _PieTotal = value; }
}
#endregion
#region PieTotalExtent
/// <summary>
/// Gets the sum total of the collection 'extents' (Y[1]).
/// </summary>
/// <returns></returns>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public double PieTotalExtent
{
get { return (_PieTotalExtent); }
internal set { _PieTotalExtent = value; }
}
#endregion
#region VisibleCount
///<summary>
/// Gets count of visible points in the collection.
///</summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int VisibleCount
{
get
{
int vcount = 0;
foreach (PieSeriesPoint psp in Items)
{
if (psp.Visible == true)
vcount++;
}
return (vcount);
}
}
#endregion
#endregion
#region Internal properties
#region PieMaxExtent
internal double PieMaxExtent
{
get { return (_PieMaxExtent); }
set { _PieMaxExtent = value; }
}
#endregion
#region PieMinExtent
internal double PieMinExtent
{
get { return (_PieMinExtent); }
set { _PieMinExtent = value; }
}
#endregion
#region PieOuterExtent
internal double PieOuterExtent
{
get { return (_PieOuterExtent); }
set { _PieOuterExtent = value; }
}
#endregion
#region PieRing
internal PieRing PieRing
{
get { return (_PieRing); }
set { _PieRing = value; }
}
#endregion
#endregion
#region ClearItems
protected override void ClearItems()
{
if (Parent is PieSeriesPoint)
{
for (int i = Items.Count - 1; i >= 0; i--)
RemoveItem(i);
}
else
{
CheckReentrancy();
Items.Clear();
OnPropertyChanged(CountString);
OnPropertyChanged(ItemString);
OnCollectionReset();
}
}
#endregion
#region SetSelected
internal void SetSelected(bool select)
{
foreach (PieSeriesPoint psp in Items)
{
if (psp != null)
{
psp.IsSelected = select;
if (psp.SeriesPoints.PieSlices != null)
psp.SeriesPoints.PieSlices.SetSelected(select);
}
}
}
#endregion
#region States
[Flags]
private enum States : uint
{
Other = (1 << 0),
}
#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 SliceVisualLayout
[TypeConverter(typeof(BlankExpandableObjectConverter))]
public class SliceVisualLayout : INotifyPropertyChanged, IProcessSerialElement, IDisposable
{
#region Private variables
private ChartVisualElement _Parent;
private double _AngleMargin = double.NaN;
private int _RingWeight = -1;
private int _MaxSlices = -1;
private int _MinExtent = -1;
private double _MinPercent = double.NaN;
private SliceLabelOrientation _InnerLabelOrientation = SliceLabelOrientation.NotSet;
private SliceLabelCropMode _SliceLabelCropMode = SliceLabelCropMode.NotSet;
private SliceLabelVisibility _SliceLabelVisibility = SliceLabelVisibility.NotSet;
private SliceLabelDisplayMode _SliceLabelDisplayMode = SliceLabelDisplayMode.NotSet;
private ChartSliceVisualStyles _SliceVisualStyles;
private ChartSliceVisualStyles _OtherSliceVisualStyles;
private Tbool _ShowSliceWhiteSpace = Tbool.NotSet;
private string _InnerSliceLabel;
private string _OuterSliceLabel;
private double _StartAngle = double.NaN;
private double _SweepAngle = double.NaN;
private SweepDirection _SweepDirection = SweepDirection.NotSet;
private string _ToolTipText;
private PieRefLineDisplayMode _RefLineDisplayMode = PieRefLineDisplayMode.NotSet;
private Tbool _ReferenceLineDisplayOnTop = Tbool.NotSet;
internal PieReferenceLineCollection _ReferenceLines;
#endregion
public SliceVisualLayout(ChartVisualElement parent)
{
_Parent = parent;
}
#region Public properties
#region AngleMargin
/// <summary>
/// Gets or sets the margin used to offset the angle at
/// which the slice sides are rendered. This can be used to
/// create a more 'wedge' shaped slice.
/// </summary>
[Description("Indicates the margin used to offset the angle at which the slice sides are rendered. This can be used to create a more 'wedge' shaped slice.")]
[DefaultValue(double.NaN)]
[Editor("DevComponents.Charts.Design.AngleMarginRangeValueEditor, DevComponents.Charts.Design, " +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public double AngleMargin
{
get { return (_AngleMargin); }
set
{
if (value != _AngleMargin)
{
_AngleMargin = value;
OnPropertyChangedEx("AngleMargin", VisualChangeType.Layout);
}
}
}
#endregion
#region InnerLabelOrientation
/// <summary>
/// Gets or sets the inner label orientation with respect to the slice.
/// </summary>
[Category("Behavior"), DefaultValue(SliceLabelOrientation.NotSet)]
[Description("Indicates the inner label orientation with respect to the slice.")]
public SliceLabelOrientation InnerLabelOrientation
{
get { return (_InnerLabelOrientation); }
set
{
if (value != _InnerLabelOrientation)
{
_InnerLabelOrientation = value;
OnPropertyChangedEx("InnerLabelOrientation", VisualChangeType.Layout);
}
}
}
#endregion
#region InnerSliceLabel
/// <summary>
/// Gets or sets the inner slice label for the pie slice. The label can be
/// straight text, or be comprised of text and formatting specifiers. The label
/// should be specified as (note that brackets denote optional elements):
/// "[text]{keyword[:format]}[text][{...}]".
///
/// Here are the formatting specifiers that can be used with both inner and
/// outer labels:
///
/// "AVG" "A" - Average (angular values).
/// "PCT" "P" - Percent of pie (angular values) - (.025 yields "2.5 %").
/// "TOT" "T" - Total of all values (angluar values).
/// "VAL" "V" - Value percent of pie (angular value) - (.025 yields ".025").
///
/// "AVGX" "AX" - Average (extent/radial values).
/// "PCTX" "PX" - Percent of pie (extent values) - (.025 yields "2.5 %").
/// "TOTX" "TX" - Total of all values (extent values).
/// "VALX" "VX" - Value percent of pie (extent value) - (.025 yields ".025").
///
/// "S" "SNAME" - Series name.
/// "X" - ValueX.
/// "Y", "Y0", "Yn" - ValueY values (where 'n' is index value).
///
/// Example use:
///
/// "{S}\\n{X:yyyy} ({Y:##,##0} - {P:Y1})"
/// "Individual cost {Y:C} and average cost {AVG:C} of goods."
///
/// </summary>
[DefaultValue(null), Category("Label")]
[Editor(typeof(MultilineStringEditor), typeof(UITypeEditor))]
[Description("Indicates the inner slice label for the pie slices (format specifiers {Keyword[:Format]} - " +
"S, X, Y, Y0-Yn, N, [A|AVG][X], [A|PCT][X], [A|TOT][X], [A|VAL][X]. e.g. \"{x:f2},{avg:##.##},{totx:c}\"")]
public string InnerSliceLabel
{
get { return (_InnerSliceLabel); }
set
{
if (String.Equals(value, _InnerSliceLabel) == false)
{
_InnerSliceLabel = value;
OnPropertyChangedEx("InnerSliceLabel", VisualChangeType.Layout);
}
}
}
#endregion
#region MaxSlices
/// <summary>
/// Gets or sets the maximum number of slices to represent in the pie. Any remaining values
/// are consolidated into the 'Other' slice, if shown, or are not displayed at all.
///
/// The slices are counted in the order in which they are displayed. This order is
/// affected by the ReverseSlices property.
/// </summary>
[DefaultValue(-1), Category("Display")]
[Description("Indicates the maximum number of slices to represent in the pie. Any remaining values are consolidated into the 'Other' slice, if shown, or are not displayed at all.")]
public int MaxSlices
{
get { return (_MaxSlices); }
set
{
if (value != _MaxSlices)
{
_MaxSlices = value;
OnPropertyChangedEx("MaxSlices", VisualChangeType.Recalc);
}
}
}
#endregion
#region MinExtent
///<summary>
/// Gets or sets the minimum extent for the collection.
///</summary>
[DefaultValue(-1), Category("Display")]
[Description("Indicates the minimum extent for the collection.")]
public int MinExtent
{
get { return (_MinExtent); }
set
{
if (value != _MinExtent)
{
_MinExtent = value;
OnPropertyChangedEx("MinExtent", Style.VisualChangeType.Recalc);
}
}
}
#endregion
#region MinPercent
/// <summary>
/// Gets or sets the minimum percent-of-total represented in individual slices.
/// Values less than the MinPercent are either accumulated into the 'Other' slice, if shown,
/// or left in the main pie display.
/// Range is 01.
/// </summary>
[DefaultValue(double.NaN), Category("Display")]
[Description("Indicates the minimum percent-of-total represented in individual slices. Values less than the MinPercent are accumulated into the 'Other' slice. Range is 01.")]
public double MinPercent
{
get { return (_MinPercent); }
set
{
if (value != _MinPercent)
{
_MinPercent = value;
OnPropertyChangedEx("MinPercent", VisualChangeType.Recalc);
}
}
}
#endregion
#region OtherSliceVisualStyles
/// <summary>
/// Gets or sets the default visual style for the series 'Other' slice.
/// </summary>
[Category("Style")]
[Description("Indicates the default visual style for the series 'Other' slice.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ChartSliceVisualStyles OtherSliceVisualStyles
{
get
{
if (_OtherSliceVisualStyles == null)
{
_OtherSliceVisualStyles = new ChartSliceVisualStyles();
StyleChangeHandler(null, _OtherSliceVisualStyles);
}
return (_OtherSliceVisualStyles);
}
set
{
if (_OtherSliceVisualStyles != value)
{
ChartSliceVisualStyles oldValue = _OtherSliceVisualStyles;
_OtherSliceVisualStyles = value;
OnStyleChanged("OtherSliceVisualStyles", oldValue, value);
if (oldValue != null)
oldValue.Dispose();
}
}
}
#endregion
#region OuterSliceLabel
/// <summary>
/// Gets or sets the outer slice label for the pie slice. See InnerSliceLabel for
/// further notes on Format Specifiers.
/// </summary>
[DefaultValue(null), Category("Label")]
[Editor(typeof(MultilineStringEditor), typeof(UITypeEditor))]
[Description("Indicates the inner slice label for the pie slices. See InnerSliceLabel for further notes on Format Specifiers.")]
public string OuterSliceLabel
{
get { return (_OuterSliceLabel); }
set
{
if (String.Equals(value, _OuterSliceLabel) == false)
{
_OuterSliceLabel = value;
OnPropertyChangedEx("OuterSliceLabel", VisualChangeType.Layout);
}
}
}
#endregion
#region Parent
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public ChartVisualElement Parent
{
get { return (_Parent); }
internal set
{
_Parent = value;
UpdateRelations();
}
}
#region UpdateRelations
private void UpdateRelations()
{
foreach (PieReferenceLine line in ReferenceLines)
line.Parent = _Parent;
}
#endregion
#endregion
#region ReferenceLineDisplayMode
/// <summary>
/// Gets or sets the type of pie reference lines to display.
/// </summary>
[Category("Appearance"), DefaultValue(PieRefLineDisplayMode.NotSet)]
[Description("Indicates the type of pie reference lines to display.")]
[Editor("DevComponents.Charts.Design.FlagsEnumUIEditor, DevComponents.Charts.Design, " +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public PieRefLineDisplayMode ReferenceLineDisplayMode
{
get { return (_RefLineDisplayMode); }
set
{
if (value != _RefLineDisplayMode)
{
_RefLineDisplayMode = value;
OnPropertyChangedEx("ReferenceLineDisplayMode", VisualChangeType.Render);
}
}
}
#endregion
#region ReferenceLineDisplayOnTop
/// <summary>
/// Gets or sets whether references lines are displayed on top of chart data.
/// </summary>
[DefaultValue(Tbool.NotSet), Category("Appearance")]
[Description("Indicates whether the reference lines are displayed on top of chart data.")]
public Tbool ReferenceLineDisplayOnTop
{
get { return (_ReferenceLineDisplayOnTop); }
set
{
if (value != _ReferenceLineDisplayOnTop)
{
_ReferenceLineDisplayOnTop = value;
OnPropertyChangedEx("ReferenceLineDisplayOnTop", VisualChangeType.Render);
}
}
}
#endregion
#region ReferenceLines
/// <summary>
/// Gets a reference to the collection of user defined Reference Lines.
/// </summary>
[Category("Appearance")]
[Description("Indicates the collection of user defined Reference Lines.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public PieReferenceLineCollection ReferenceLines
{
get
{
if (_ReferenceLines == null)
{
_ReferenceLines = new PieReferenceLineCollection();
_ReferenceLines.CollectionChanged += ReferenceLineCollectionChanged;
}
return (_ReferenceLines);
}
internal set
{
if (_ReferenceLines != null)
_ReferenceLines.CollectionChanged -= ReferenceLineCollectionChanged;
_ReferenceLines = value;
if (_ReferenceLines != null)
_ReferenceLines.CollectionChanged += ReferenceLineCollectionChanged;
}
}
#region ReferenceLineCollectionChanged
void ReferenceLineCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (ChartElement item in e.NewItems)
{
item.Parent = Parent;
item.PropertyChanged += Item_PropertyChanged;
}
break;
case NotifyCollectionChangedAction.Replace:
foreach (ChartElement item in e.OldItems)
{
item.Parent = null;
item.PropertyChanged -= Item_PropertyChanged;
}
foreach (ChartElement item in e.NewItems)
{
item.Parent = Parent;
item.PropertyChanged += Item_PropertyChanged;
}
break;
case NotifyCollectionChangedAction.Remove:
foreach (ChartElement item in e.OldItems)
{
item.Parent = null;
item.PropertyChanged -= Item_PropertyChanged;
}
break;
}
OnPropertyChangedEx("ReferenceLines", VisualChangeType.Render);
}
void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
OnPropertyChanged(e);
}
#endregion
#endregion
#region RingWeight
///<summary>
/// Gets or sets the 'relative' thickness of the associated pie ring, as
/// compared to the relative thickness of other series rings
/// rings.
///</summary>
[DefaultValue(-1), Category("Layout")]
[Description("Indicates the 'relative' thickness of the associated pie ring, as compared to the relative thickness of other series rings. Default is 100.")]
public int RingWeight
{
get { return (_RingWeight); }
set
{
if (value != _RingWeight)
{
_RingWeight = value;
OnPropertyChangedEx("RingWeight", Style.VisualChangeType.Recalc);
}
}
}
#endregion
#region ShowSliceWhiteSpace
/// <summary>
/// Gets or sets whether to display, by default, the full
/// slice (includes potential area beyond slice extent). Default is false.
/// </summary>
[DefaultValue(Tbool.NotSet), Category("Display")]
[Description("Indicates whether to display, by default the full slice (includes potential area beyond slice extent). Default is false.")]
public Tbool ShowSliceWhiteSpace
{
get { return (_ShowSliceWhiteSpace); }
set
{
if (value != _ShowSliceWhiteSpace)
{
_ShowSliceWhiteSpace = value;
OnPropertyChangedEx("ShowSliceWhiteSpace", VisualChangeType.Layout);
}
}
}
#endregion
#region SliceLabelCropMode
/// <summary>
/// Gets or sets the label display mode (ie. the action taken
/// when a label needs be clipped for full display). Default is Clip.
/// </summary>
[DefaultValue(SliceLabelCropMode.NotSet), Category("Label")]
[Description("Indicates the label display mode (ie. the action taken when a label needs clipped for full display). Default is Clip.")]
public SliceLabelCropMode SliceLabelCropMode
{
get { return (_SliceLabelCropMode); }
set
{
if (value != _SliceLabelCropMode)
{
_SliceLabelCropMode = value;
OnPropertyChangedEx("SliceLabelCropMode", VisualChangeType.Layout);
}
}
}
#endregion
#region SliceLabelVisibility
/// <summary>
/// Gets or sets when the slice labels are visibly displayed.
/// </summary>
[DefaultValue(SliceLabelVisibility.NotSet), Category("Label")]
[Description("Indicates when the slice labels are visibly displayed.")]
public SliceLabelVisibility SliceLabelVisibility
{
get { return (_SliceLabelVisibility); }
set
{
if (value != _SliceLabelVisibility)
{
_SliceLabelVisibility = value;
OnPropertyChangedEx("SliceLabelVisibility", VisualChangeType.Layout);
}
}
}
#endregion
#region SliceLabelDisplayMode
/// <summary>
/// Gets or sets the label display mode, which determines
/// which slice labels (inner/outer) are displayed. Default is InnerAndOuter.
/// </summary>
[DefaultValue(SliceLabelDisplayMode.NotSet), Category("Label")]
[Description("Indicates the label display mode, which determines which slice labels (inner/outer) are displayed. Default is InnerAndOuter.")]
public SliceLabelDisplayMode SliceLabelDisplayMode
{
get { return (_SliceLabelDisplayMode); }
set
{
if (value != _SliceLabelDisplayMode)
{
_SliceLabelDisplayMode = value;
OnPropertyChangedEx("SliceLabelDisplayMode", VisualChangeType.Layout);
}
}
}
#endregion
#region SliceVisualStyles
/// <summary>
/// Gets or sets the visual styles for the slice.
/// </summary>
[Category("Style")]
[Description("Indicates the visual styles for the slice.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ChartSliceVisualStyles SliceVisualStyles
{
get
{
if (_SliceVisualStyles == null)
{
_SliceVisualStyles = new ChartSliceVisualStyles();
StyleChangeHandler(null, _SliceVisualStyles);
}
return (_SliceVisualStyles);
}
set
{
if (_SliceVisualStyles != value)
{
ChartSliceVisualStyles oldValue = _SliceVisualStyles;
_SliceVisualStyles = value;
OnStyleChanged("SliceVisualStyles", oldValue, value);
if (oldValue != null)
oldValue.Dispose();
}
}
}
#endregion
#region StartAngle
/// <summary>
/// Gets or sets the start angle of the pie in degrees where 0 is right and 270 is top.
/// Defaults to 270.
/// </summary>
[DefaultValue(double.NaN), Category("Layout")]
[Description("Indicates the start angle of the pie in degrees where 0 is right and 270 is top. Defaults to 270.")]
[Editor("DevComponents.Charts.Design.AngleRangeValueEditor, DevComponents.Charts.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public double StartAngle
{
get { return (_StartAngle); }
set
{
if (value != _StartAngle)
{
_StartAngle = value;
OnPropertyChangedEx("StartAngle", VisualChangeType.Layout);
}
}
}
#endregion
#region SweepAngle
/// <summary>
/// Gets or sets the sweep angle (distance from StartAngle to the
/// ending angle) of the pie in positive degrees (use SweepDirection
/// to change rotational direction).
/// </summary>
[DefaultValue(double.NaN), Category("Layout")]
[Description("Indicates the sweep angle (distance from StartAngle to the ending angle) of the pie in positive degrees (use SweepDirection to change rotational direction).")]
[Editor("DevComponents.Charts.Design.AngleRangeValueEditor, DevComponents.Charts.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public double SweepAngle
{
get { return (_SweepAngle); }
set
{
if (value != _SweepAngle)
{
if (value < 0)
throw new Exception("SweepAngle cannot be negative (See SweepDirection).");
_SweepAngle = value;
OnPropertyChangedEx("SweepAngle", VisualChangeType.Layout);
}
}
}
#endregion
#region SweepDirection
/// <summary>
/// Gets or sets the direction to display the pie slices - in either a clockwise
/// or counterclockwise direction.
/// </summary>
[DefaultValue(SweepDirection.NotSet), Category("Layout")]
[Description("Indicates the direction to display the pie slices - in either a clockwise or counterclockwise direction).")]
public SweepDirection SweepDirection
{
get { return (_SweepDirection); }
set
{
if (value != _SweepDirection)
{
_SweepDirection = value;
OnPropertyChangedEx("SweepDirection", VisualChangeType.Recalc);
}
}
}
#endregion
#region ToolTipText
/// <summary>
/// Gets or sets the text to use for the point ToolTip.
/// </summary>
[DefaultValue(null), Category("Label")]
[Description("Indicates the text to use for the point ToolTip.")]
[Editor(typeof(MultilineStringEditor), typeof(UITypeEditor))]
public string ToolTipText
{
get { return (_ToolTipText); }
set
{
if (value != _ToolTipText)
{
_ToolTipText = value;
OnPropertyChanged("ToolTipText");
}
}
}
#endregion
#endregion
#region GetReferenceLineByName
/// <summary>
/// Gets the ReferenceLine from the given name.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public PieReferenceLine GetReferenceLineByName(string name)
{
if (String.IsNullOrEmpty(name) == true)
return (null);
if (_ReferenceLines != null)
{
foreach (PieReferenceLine line in _ReferenceLines)
{
if (name.Equals(line.Name) == true)
return (line);
}
}
return (null);
}
#endregion
#region Style support
#region OnStyleChanged
protected virtual void OnStyleChanged(string property,
INotifyPropertyChanged oldValue, INotifyPropertyChanged newValue)
{
StyleChangeHandler(oldValue, newValue);
OnPropertyChanged(property);
}
#endregion
#region StyleChangeHandler
protected void StyleChangeHandler(
INotifyPropertyChanged oldValue, INotifyPropertyChanged newValue)
{
if (oldValue != null)
oldValue.PropertyChanged -= StyleChanged;
if (newValue != null)
newValue.PropertyChanged += StyleChanged;
}
#region StyleChanged
/// <summary>
/// Occurs when one of element visual styles has property changes.
/// Default implementation invalidates visual appearance of element.
/// </summary>
/// <param name="sender">VisualStyle that changed.</param>
/// <param name="e">Event arguments.</param>
protected void StyleChanged(object sender, PropertyChangedEventArgs e)
{
OnPropertyChanged(e);
}
#endregion
#endregion
#region INotifyPropertyChanged Members
/// <summary>
/// Occurs when property value has changed.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
#region OnPropertyChanged
/// <summary>
/// Raises the PropertyChanged event.
/// </summary>
/// <param name="e">Event arguments</param>
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
PropertyChanged(this, e);
}
/// <summary>
/// Default PropertyChanged processing
/// </summary>
/// <param name="s"></param>
protected void OnPropertyChanged(string s)
{
if (PropertyChanged != null)
OnPropertyChanged(new PropertyChangedEventArgs(s));
}
/// <summary>
/// Default PropertyChanged processing
/// </summary>
/// <param name="s"></param>
/// <param name="changeType">invalidate</param>
protected void OnPropertyChangedEx(string s, VisualChangeType changeType)
{
if (PropertyChanged != null)
OnPropertyChanged(new VisualPropertyChangedEventArgs(s, changeType));
}
#endregion
#endregion
#endregion
#region Copy/CopyTo
/// <summary>
/// Creates a copy of the SeriesPointsLayout
/// </summary>
/// <returns></returns>
public SliceVisualLayout Copy()
{
SliceVisualLayout copy = new SliceVisualLayout(null);
CopyTo(copy);
return (copy);
}
/// <summary>
/// Copies the item data to the given SeriesPointsLayout.
/// </summary>
/// <param name="sp"></param>
public void CopyTo(SliceVisualLayout c)
{
c.AngleMargin = AngleMargin;
c.MaxSlices = MaxSlices;
c.MinExtent = MinExtent;
c.MinPercent = MinPercent;
c.InnerLabelOrientation = _InnerLabelOrientation;
c.InnerSliceLabel = _InnerSliceLabel;
c.OtherSliceVisualStyles = (_OtherSliceVisualStyles != null) ? _OtherSliceVisualStyles.Copy() : null;
c.OuterSliceLabel = OuterSliceLabel;
foreach (PieReferenceLine line in ReferenceLines)
c.ReferenceLines.Add((PieReferenceLine)line.Copy());
c.ReferenceLineDisplayMode = _RefLineDisplayMode;
c.ReferenceLineDisplayOnTop = _ReferenceLineDisplayOnTop;
c.RingWeight = RingWeight;
c.ShowSliceWhiteSpace = _ShowSliceWhiteSpace;
c.SliceLabelCropMode = _SliceLabelCropMode;
c.SliceLabelDisplayMode = _SliceLabelDisplayMode;
c.SliceLabelVisibility = _SliceLabelVisibility;
c.SliceVisualStyles = (_SliceVisualStyles != null) ? _SliceVisualStyles.Copy() : null;
c.StartAngle = _StartAngle;
c.SweepAngle = _SweepAngle;
c.SweepDirection = _SweepDirection;
}
#endregion
#region GetSerialData
internal virtual SerialElementCollection GetSerialData()
{
return (GetSerialData(true));
}
internal virtual SerialElementCollection GetSerialData(bool root)
{
SerialElementCollection sec = new SerialElementCollection();
if (root == true)
sec.AddStartElement("SliceVisualLayout");
sec.AddValue("AngleMargin", AngleMargin, double.NaN);
sec.AddValue("MaxSlices", MaxSlices, -1);
sec.AddValue("MinExtent", MinExtent, -1);
sec.AddValue("MinPercent", MinPercent, double.NaN);
sec.AddValue("InnerLabelOrientation", InnerLabelOrientation, SliceLabelOrientation.NotSet);
sec.AddValue("InnerSliceLabel", InnerSliceLabel, null);
if (_OtherSliceVisualStyles != null && _OtherSliceVisualStyles.IsEmpty == false)
sec.AddElement(_OtherSliceVisualStyles.GetSerialData("OtherSliceVisualStyles"));
sec.AddValue("OuterSliceLabel", OuterSliceLabel, null);
if (_ReferenceLines != null && _ReferenceLines.Count > 0)
{
sec.AddStartElement("ReferenceLines count=\"" + _ReferenceLines.Count + "\"");
foreach (PieReferenceLine rline in _ReferenceLines)
sec.AddElement(rline.GetSerialData(""));
sec.AddEndElement("ReferenceLines");
}
sec.AddValue("ReferenceLineDisplayMode", ReferenceLineDisplayMode, PieRefLineDisplayMode.NotSet);
sec.AddValue("ReferenceLineDisplayOnTop", ReferenceLineDisplayOnTop, Tbool.NotSet);
sec.AddValue("RingWeight", RingWeight, -1);
sec.AddValue("ShowSliceWhiteSpace", ShowSliceWhiteSpace, Tbool.NotSet);
sec.AddValue("SliceLabelCropMode", SliceLabelCropMode, SliceLabelCropMode.NotSet);
sec.AddValue("SliceLabelDisplayMode", SliceLabelDisplayMode, SliceLabelDisplayMode.NotSet);
sec.AddValue("SliceLabelVisibility", SliceLabelVisibility, SliceLabelVisibility.NotSet);
if (_SliceVisualStyles != null && _SliceVisualStyles.IsEmpty == false)
sec.AddElement(_SliceVisualStyles.GetSerialData("SliceVisualStyles"));
sec.AddValue("StartAngle", StartAngle, double.NaN);
sec.AddValue("SweepAngle", SweepAngle, double.NaN);
sec.AddValue("SweepDirection", SweepDirection, SweepDirection.NotSet);
if (root == true)
sec.AddEndElement("SliceVisualLayout");
return (sec);
}
#endregion
#region PutSerialData
#region ProcessValue
void IProcessSerialElement.ProcessValue(SerialElement se)
{
switch (se.Name)
{
case "AngleMargin":
AngleMargin = double.Parse(se.StringValue);
break;
case "InnerLabelOrientation":
InnerLabelOrientation = (SliceLabelOrientation)se.GetValueEnum(typeof(SliceLabelOrientation));
break;
case "InnerSliceLabel":
InnerSliceLabel = se.StringValue;
break;
case "MaxSlices":
MaxSlices = int.Parse(se.StringValue);
break;
case "MinExtent":
MinExtent = int.Parse(se.StringValue);
break;
case "MinPercent":
MinPercent = double.Parse(se.StringValue);
break;
case "OuterSliceLabel":
OuterSliceLabel = se.StringValue;
break;
case "ReferenceLineDisplayMode":
ReferenceLineDisplayMode = (PieRefLineDisplayMode)se.GetValueEnum(typeof(PieRefLineDisplayMode));
break;
case "ReferenceLineDisplayOnTop":
ReferenceLineDisplayOnTop = (Tbool)se.GetValueEnum(typeof(Tbool));
break;
case "RingWeight":
RingWeight = int.Parse(se.StringValue);
break;
case "ShowSliceWhiteSpace":
ShowSliceWhiteSpace = (Tbool)se.GetValueEnum(typeof(Tbool));
break;
case "SliceLabelCropMode":
SliceLabelCropMode = (SliceLabelCropMode)se.GetValueEnum(typeof(SliceLabelCropMode));
break;
case "SliceLabelDisplayMode":
SliceLabelDisplayMode = (SliceLabelDisplayMode)se.GetValueEnum(typeof(SliceLabelDisplayMode));
break;
case "SliceLabelVisibility":
SliceLabelVisibility = (SliceLabelVisibility)se.GetValueEnum(typeof(SliceLabelVisibility));
break;
case "StartAngle":
StartAngle = double.Parse(se.StringValue);
break;
case "SweepAngle":
SweepAngle = double.Parse(se.StringValue);
break;
case "SweepDirection":
SweepDirection = (SweepDirection)se.GetValueEnum(typeof(SweepDirection));
break;
}
}
#endregion
#region ProcessCollection
void IProcessSerialElement.ProcessCollection(SerialElement se)
{
SerialElementCollection sec = se.Sec;
switch (se.Name)
{
case "OtherSliceVisualStyles":
sec.PutSerialData(OtherSliceVisualStyles);
break;
case "ReferenceLine":
PieReferenceLine line = GetReferenceLineByName(se.Name);
if (line != null)
sec.PutSerialData(line);
break;
case "ReferenceLines":
sec.PutSerialData(this);
break;
case "SliceVisualStyles":
sec.PutSerialData(SliceVisualStyles);
break;
}
}
#endregion
#endregion
#region IDispose
public virtual void Dispose()
{
ReferenceLines = null;
OtherSliceVisualStyles = null;
SliceVisualStyles = null;
Parent = null;
}
#endregion
}
#region ISeriesPointContainer
public interface ISeriesPointContainer
{
SliceVisualLayout SubSliceVisualLayout { get; set; }
}
#endregion
#endregion
#region PieSeriesPoint
[DesignTimeVisible(false), ToolboxItem(false)]
public class PieSeriesPoint : SeriesPoint,
IEffectiveStyle, INotifyPropertyChanged, ILegendItem, ILegendItemEx, ISeriesPointContainer, INamed
{
#region Private variables
private object _Parent;
private int _OrdinalValue;
private ChartControl _ChartControl;
private int _LocalUpdateCount;
private string _InnerSliceLabel;
private string _OuterSliceLabel;
private double _DetachedOffset = double.NaN;
private double _StartAngle = double.NaN;
private double _SweepAngle = double.NaN;
private double _AngleMarginExx;
private double _StartAngleEx;
private double _SweepAngleEx;
private Point _SliceCenter;
private double _SliceExtent;
private double _SliceValue;
private int _InnerRadius;
private int _OuterRadius;
private Rectangle _PathBounds;
private Rectangle _LastPathBounds;
private PieRing _PieRing;
private PieSeriesPoint _RootPsp;
private ChartSliceVisualStyles _SliceVisualStyles;
private EffectiveStyles<ChartSliceVisualStyle> _EffectiveSliceStyles;
private ChartSliceVisualStyle _LastEffectiveStyle;
private Color _DefaultPaletteColor = Color.Empty;
private ushort _LayoutUpdateCount;
private Rectangle _InscribedRect;
private List<WordPosLine> _WordPosLines;
private RectangleF[] _CharBounds;
private PieLabel _PieLabel;
private ChartLegendItem _LegendItem;
private string _LegendText;
private ChartLegendItemVisualStyles _ChartLegendItemVisualStyles;
private string _Name;
private string _ToolTipText;
private PieSeriesPointCollection _SeriesPoints;
private SliceVisualLayout _SliceVisualLayout;
private States _States;
// ---- Cached items
private double _AngleMarginEx;
private SliceLabelCropMode _SliceLabelCropModeEx;
private SliceLabelDisplayMode _SliceLabelDisplayModeEx;
private SliceLabelOrientation _InnerLabelOrientationEx;
private SliceLabelVisibility _SliceLabelVisibilityEx;
private string _InnerSliceLabelEx;
private string _OuterSliceLabelEx;
private int _MaxSlicesEx;
private int _MinExtentEx;
private double _MinPercentEx;
private int _RingWeightEx;
private PieRefLineDisplayMode _ReferenceLineDisplayModeEx;
private List<PieReferenceLine> _ReferenceLinesEx;
private string _ToolTipTextEx;
#endregion
#region Constructors
public PieSeriesPoint()
: this(0, 0)
{
}
/// <summary>
/// PieSeriesPoint
/// </summary>
/// <param name="xValue"></param>
/// <param name="yValue"></param>
public PieSeriesPoint(object xValue, object yValue)
: base(xValue, yValue)
{
InitDefaultStates();
_EffectiveSliceStyles = new EffectiveStyles<ChartSliceVisualStyle>(this);
}
/// <summary>
/// PieSeriesPoint
/// </summary>
/// <param name="xValue"></param>
/// <param name="yValue"></param>
public PieSeriesPoint(object xValue, object[] yValue)
: base(xValue, yValue)
{
InitDefaultStates();
_EffectiveSliceStyles = new EffectiveStyles<ChartSliceVisualStyle>(this);
}
/// <summary>
/// PieSeriesPoint
/// </summary>
/// <param name="xValue"></param>
/// <param name="yValue1">angular value</param>
/// <param name="yValue2">yValue2=radial</param>
public PieSeriesPoint(object xValue, object yValue1, object yValue2)
: base(xValue, yValue1, yValue2)
{
InitDefaultStates();
_EffectiveSliceStyles = new EffectiveStyles<ChartSliceVisualStyle>(this);
}
#endregion
#region InitDefaultStates
private void InitDefaultStates()
{
SetState(States.AllowDetach, true);
SetState(States.AllowSelect, true);
SetState(States.CheckedInLegend, true);
SetState(States.ShowInLegend, true);
SetState(States.ShowInParentLegend, true);
SetState(States.ShowMarkerInLegend, true);
}
#endregion
#region Public properties
#region ActualStartAngle
/// <summary>
/// Gets the actual, calculated starting angle for the slice.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public double ActualStartAngle
{
get { return (StartAngleEx); }
}
#endregion
#region ActualSweepAngle
/// <summary>
/// Gets the actual, calculated sweep angle for the slice.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public double ActualSweepAngle
{
get { return (SweepAngleEx); }
}
#endregion
#region AllowDetach
/// <summary>
/// Gets or sets whether the element can be 'detached' from
/// the center of the pie by the user. Defaults to true.
/// </summary>
[DefaultValue(true), Category("Behavior")]
[Description("Indicates whether the element can be 'detached' from the center of the pie by the user. Defaults to true.")]
public bool AllowDetach
{
get { return (TestState(States.AllowDetach)); }
set
{
if (value != AllowDetach)
{
SetState(States.AllowDetach, value);
OnPropertyChanged("AllowDetach");
}
}
}
#endregion
#region AllowSelect
/// <summary>
/// Gets or sets whether the element can be selected by clicking on it. Defaults to true.
/// </summary>
[DefaultValue(true), Category("Behavior")]
[Description("Indicates whether the element can be selected by clicking on it. Defaults to true.")]
public bool AllowSelect
{
get { return (TestState(States.AllowSelect)); }
set
{
if (value != AllowSelect)
{
SetState(States.AllowSelect, value);
OnPropertyChanged("AllowSliceSelect");
}
}
}
#endregion
#region CenterAngle
/// <summary>
/// Gets the Center Angle for the slice.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public double CenterAngle
{
get { return ((StartAngleEx + SweepAngleEx / 2) + 360000) % 360; }
}
#endregion
#region ChartSeries
/// <summary>
/// Gets the associated ChartSeries.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public PieSeries ChartSeries
{
get { return (_PieRing != null ? _PieRing.ChartSeries : null); }
}
#endregion
#region DefaultPaletteColor
/// <summary>
/// Gets the default palette color assigned to the point when it
/// is arranged in the pie.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("Indicates the default palette color assigned to the point when it is arranged in the pie.")]
public Color DefaultPaletteColor
{
get { return (_DefaultPaletteColor); }
internal set
{
if (value != _DefaultPaletteColor)
{
_DefaultPaletteColor = value;
ClearEffectiveStyles();
OnPropertyChangedEx("DetachedOffset", VisualChangeType.Render);
}
}
}
#endregion
#region DetachedOffset
/// <summary>
/// Gets or sets the offset distance of the slice from the pie center, as measured
/// by a percentage of the pie radius (if between 0 and 1), or absolute pixel amount (if >= 1).
/// </summary>
[DefaultValue(double.NaN), Category("Appearance")]
[Description("Indicates the offset distance of the slice from the pie center, as measured by a percentage of the pie radius (if between 0 and 1), or absolute pixel amount (if >= 1).")]
[Editor("DevComponents.Charts.Design.RadiusRangeValueEditor, DevComponents.Charts.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public double DetachedOffset
{
get { return (_DetachedOffset); }
set
{
if (value != _DetachedOffset)
{
_DetachedOffset = value;
OnPropertyChangedEx("DetachedOffset", VisualChangeType.Layout);
}
}
}
#endregion
#region EffectiveSliceStyles
/// <summary>
/// Gets a reference to the Effective (cached, composite) Slice styles.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public EffectiveStyles<ChartSliceVisualStyle> EffectiveSliceStyles
{
get { return (_EffectiveSliceStyles); }
}
#endregion
#region ExtentRadius
/// <summary>
/// Gets the actual, calculated extent radius of the slice (the
/// radius between the inner and outer radius - ValuesY[1]).
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public double ExtentRadius
{
get
{
int width = OuterRadius - InnerRadius;
int extendWidth = (int)(SliceExtent * width);
return (InnerRadius + extendWidth);
}
}
#endregion
#region InnerRadius
/// <summary>
/// Gets the actual, inner radius of the slice.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int InnerRadius
{
get { return (_InnerRadius); }
internal set { _InnerRadius = value; }
}
#endregion
#region InnerSliceLabel
/// <summary>
/// Gets or sets the inner slice label for the pie slice. The label can be
/// straight text, or be comprised of text and formatting specifiers. The label
/// should be specified as "Some text {Keyword:Format} more text [{...:...}]".
///
/// Here are the formatting specifiers that can be used with both inner and
/// outer labels:
///
/// "AVG" "A" - Average (angular values).
/// "PCT" "P" - Percent of pie (angular values) - (.025 yields "2.5 %").
/// "TOT" "T" - Total of all values (angluar values).
/// "VAL" "V" - Value percent of pie (angular value) - (.025 yields ".025").
///
/// "AVGX" "AX" - Average (extent/radial values).
/// "PCTX" "PX" - Percent of pie (extent values) - (.025 yields "2.5 %").
/// "TOTX" "TX" - Total of all values (extent values).
/// "VALX" "VX" - Value percent of pie (extent value) - (.025 yields ".025").
///
/// "S" "SNAME" - Series name.
/// "X" - ValueX.
/// "Y", "Y0", "Yn" - ValueY values (where 'n' is index value).
///
/// Examples:
///
/// "{S}\\n{X:yyyy} ({Y:##,##0} - {P:Y1})"
/// "Individual cost {Y:C} and average cost {AVG:C} of goods."
///
/// </summary>
[DefaultValue(null), Category("Label")]
[Editor(typeof(MultilineStringEditor), typeof(UITypeEditor))]
[Description("Indicates the inner slice label for the pie slices (format specifiers {Keyword[:Format]} - " +
"S, X, Y, Y0-Yn, N, [A|AVG][X], [A|PCT][X], [A|TOT][X], [A|VAL][X]. e.g. \"{x:f2},{avg:##.##},{totx:c}\"")]
public string InnerSliceLabel
{
get { return (_InnerSliceLabel); }
set
{
if (String.Equals(value, _InnerSliceLabel) == false)
{
_InnerSliceLabel = value;
OnPropertyChangedEx("InnerSliceLabel", VisualChangeType.Layout);
}
}
}
#endregion
#region IsDetached
/// <summary>
/// Gets or sets whether the slice is 'detached' from the center of the pie. This can be
/// used to create emphasis or to highlight a slice of the pie.
/// </summary>
[DefaultValue(false), Category("Appearance")]
[Description("Indicates whether the slice is 'detached' from the center of the pie.")]
public bool IsDetached
{
get { return (TestState(States.Detached)); }
set
{
if (value != IsDetached)
{
SetState(States.Detached, value);
OnPropertyChangedEx("IsDetached", VisualChangeType.Layout);
}
}
}
#endregion
#region IsDisplayed
///<summary>
/// Gets whether the series point is displayed
/// based upon its Visibility and Legend state.
///</summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool IsDisplayed
{
get { return (Visible == true && IsDisplayedEx == true); }
}
#endregion
#region IsEmptyPoint
/// <summary>
/// Gets or sets whether the point is an 'Empty' (or missing) Point.
/// </summary>
[DefaultValue(false), Category("Data")]
[Description("Indicates whether the point is an 'Empty' (or missing) Point.")]
public override bool IsEmptyPoint
{
get { return (base.IsEmptyPoint); }
set
{
if (value != base.IsEmptyPoint)
{
base.IsEmptyPoint = value;
OnPropertyChangedEx("IsEmptyPoint", VisualChangeType.Recalc);
}
}
}
#endregion
#region IsInOther
/// <summary>
/// Gets whether the slice is in the 'Other' slice.
/// </summary>
[DefaultValue(false), Category("Appearance")]
[Description("Indicates whether the slice is in the 'Other' slice.")]
public bool IsInOther
{
get { return (TestState(States.IsInOther)); }
set
{
if (value != IsInOther)
{
SetState(States.IsInOther, value);
OnPropertyChangedEx("IsInOther", VisualChangeType.Layout);
}
}
}
#endregion
#region IsOther
/// <summary>
/// Gets whether the slice is the 'Other' slice.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("Indicates whether the slice is the 'Other' slice.")]
public bool IsOther
{
get { return (TestState(States.IsOther)); }
internal set { SetState(States.IsOther, value); }
}
#endregion
#region IsSelected
/// <summary>
/// Gets or sets whether the slice is selected.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("Indicates whether the slice is selected.")]
public bool IsSelected
{
get { return (TestState(States.Selected)); }
set
{
if (value != IsSelected)
{
SetState(States.Selected, value);
OnPropertyChangedEx("IsSelected", VisualChangeType.Render);
PieSeries series = ChartSeries;
if (series != null)
{
PieChart pieChart = series.Parent as PieChart;
if (pieChart != null)
pieChart.GlobalSelectionCount++;
}
}
}
}
#endregion
#region Name
/// <summary>
/// Gets or sets the Name of the item.
/// </summary>
[DefaultValue(null)]
[Description("Indicates the Name of the item.")]
public virtual string Name
{
get { return (_Name); }
set { _Name = value; }
}
#endregion
#region OrdinalValue
/// <summary>
/// Gets the ordial value for the point (the ordinal value when added
/// to the PieSeriesPoint Collection
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int OrdinalValue
{
get { return (_OrdinalValue); }
internal set { _OrdinalValue = value; }
}
#endregion
#region OuterRadius
/// <summary>
/// Gets the actual, outer radius of the slice.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int OuterRadius
{
get { return (_OuterRadius); }
internal set { _OuterRadius = value; }
}
#endregion
#region OuterSliceLabel
/// <summary>
/// Gets or sets the outer slice label for the pie slice. See InnerSliceLabel for
/// further notes on Format Specifiers.
/// </summary>
[DefaultValue(null), Category("Label")]
[Editor(typeof(MultilineStringEditor), typeof(UITypeEditor))]
[Description("Indicates the inner slice label for the pie slices. See InnerSliceLabel for further notes on Format Specifiers.")]
public string OuterSliceLabel
{
get { return (_OuterSliceLabel); }
set
{
if (String.Equals(value, _OuterSliceLabel) == false)
{
_OuterSliceLabel = value;
OnPropertyChangedEx("OuterSliceLabel", VisualChangeType.Layout);
}
}
}
#endregion
#region Parent
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("Indicates the item Parent.")]
public object Parent
{
get { return (_Parent); }
internal set
{
_Parent = value;
_RootPsp = null;
if (value != null)
{
PieSeriesPointCollection psp = value as PieSeriesPointCollection;
if (psp != null)
SubSliceVisualLayout.Parent = psp.Parent as ChartVisualElement;
}
}
}
#endregion
#region PieRing
/// <summary>
/// Gets the items associated PieRing (if applicable).
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public PieRing PieRing
{
get { return (_PieRing); }
internal set { _PieRing = value; }
}
#endregion
#region SeriesPoints
///<summary>
/// Gets the nested series point data collection.
///</summary>
[Category("Data")]
[Description("Indicates the nested series point data collection.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public PieSeriesPointCollection SeriesPoints
{
get
{
if (_SeriesPoints == null)
SeriesPoints = new PieSeriesPointCollection();
return (_SeriesPoints);
}
set
{
if (value != _SeriesPoints)
{
if (_SeriesPoints != null)
{
_SeriesPoints.Parent = null;
_SeriesPoints.CollectionChanged -= SeriesPoints_CollectionChanged;
}
_SeriesPoints = value;
if (_SeriesPoints != null)
{
_SeriesPoints.Parent = this;
_SeriesPoints.CollectionChanged += SeriesPoints_CollectionChanged;
}
OnPropertyChangedEx("SeriesPoints", VisualChangeType.Layout);
}
}
}
#region SeriesPoints_CollectionChanged
void SeriesPoints_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
SetSpcNotify(e.OldItems, false);
SetSpcNotify(e.NewItems, true);
OnPropertyChangedEx("SeriesPoints", Style.VisualChangeType.Layout);
}
#region SetPointNotify
private void SetSpcNotify(IList list, bool notify)
{
if (list != null)
{
foreach (PieSeriesPoint psp in list)
{
if (psp != null)
{
if (notify == true)
{
psp.Parent = SeriesPoints;
psp.PropertyChanged += Spc_PropertyChanged;
}
else
{
psp.Parent = null;
psp.PropertyChanged -= Spc_PropertyChanged;
}
}
}
}
}
#endregion
#region Spc_PropertyChanged
void Spc_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e is VisualPropertyChangedEventArgs)
OnPropertyChanged(e);
}
#endregion
#endregion
#endregion
#region SliceCenter
/// <summary>
/// Gets the slice center origin point.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Point SliceCenter
{
get { return (_SliceCenter); }
internal set { _SliceCenter = value; }
}
#endregion
#region SliceExtent
/// <summary>
/// Gets the calculated slice extent value (the relative
/// percent-of-total ValuesY[1] value for the slice).
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public double SliceExtent
{
get { return (_SliceExtent); }
internal set { _SliceExtent = value; }
}
#endregion
#region SliceValue
/// <summary>
/// Gets the calculated slice value (the relative
/// percent-of-total ValuesY[0] value for the slice).
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public double SliceValue
{
get { return (_SliceValue); }
internal set { _SliceValue = value; }
}
#endregion
#region SliceVisualStyles
/// <summary>
/// Gets or sets the visual styles for the slice.
/// </summary>
[Category("Style")]
[Description("Indicates the visual styles for the slice.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ChartSliceVisualStyles SliceVisualStyles
{
get
{
if (_SliceVisualStyles == null)
{
_SliceVisualStyles = new ChartSliceVisualStyles();
StyleChangeHandler(null, _SliceVisualStyles);
}
return (_SliceVisualStyles);
}
set
{
if (_SliceVisualStyles != value)
{
ChartSliceVisualStyles oldValue = _SliceVisualStyles;
_SliceVisualStyles = value;
OnStyleChanged("SliceVisualStyles", oldValue, value);
if (oldValue != null)
oldValue.Dispose();
}
}
}
#endregion
#region StartAngle
///<summary>
/// Gets or sets the starting angle of the slice. For subsequent slices,
/// the default is the ending angle of the previous slice. Specify a value
/// for the StartAngle if you want the next slice to start at an angle that
/// is different from the previous ending angle.
///</summary>
[DefaultValue(double.NaN), Category("Layout")]
[Description("Indicates the starting angle of the slice. For subsequent slices, the default is the ending angle of the previous slice. Specify a value for the StartAngle if you want the next slice to start at an angle that is different from the previous ending angle.")]
[Editor("DevComponents.Charts.Design.AngleRangeValueEditor, DevComponents.Charts.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public double StartAngle
{
get { return (_StartAngle); }
set
{
if (value != _StartAngle)
{
_StartAngle = value;
OnPropertyChangedEx("StartAngle", Style.VisualChangeType.Layout);
}
}
}
#endregion
#region SubSliceVisualLayout
/// <summary>
/// Gets or sets the layout of the subordinate (or nested) slices.
/// </summary>
[Category("Layout")]
[Description("Indicates the layout of the subordinate (or nested) slices.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public SliceVisualLayout SubSliceVisualLayout
{
get
{
if (_SliceVisualLayout == null)
SubSliceVisualLayout = new SliceVisualLayout(null);
return (_SliceVisualLayout);
}
set
{
if (value != _SliceVisualLayout)
{
if (_SliceVisualLayout != null)
_SliceVisualLayout.PropertyChanged -= SliceVisualLayout_PropertyChanged;
_SliceVisualLayout = value;
if (_SliceVisualLayout != null)
{
_SliceVisualLayout.SliceVisualStyles.Default.Tag = "PSP_Def";
_SliceVisualLayout.SliceVisualStyles.MouseOver.Tag = "PSP_Mov";
_SliceVisualLayout.SliceVisualStyles.Selected.Tag = "PSP_Sel";
_SliceVisualLayout.SliceVisualStyles.SelectedMouseOver.Tag = "PSP_Smo";
_SliceVisualLayout.PropertyChanged += SliceVisualLayout_PropertyChanged;
}
OnPropertyChangedEx("SubSliceVisualLayout", VisualChangeType.Recalc);
}
}
}
#region SliceVisualLayout_PropertyChanged
void SliceVisualLayout_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e is VisualPropertyChangedEventArgs)
OnPropertyChanged(e);
}
#endregion
#endregion
#region SweepAngle
///<summary>
/// Gets or sets the sweep angle of the slice (angle size, in degrees).
///</summary>
[DefaultValue(double.NaN), Category("Layout")]
[Description("Indicates the sweep angle of the slice (angle size, in degrees).")]
[Editor("DevComponents.Charts.Design.AngleRangeValueEditor, DevComponents.Charts.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public double SweepAngle
{
get { return (_SweepAngle); }
set
{
if (value != _SweepAngle)
{
if (value < 0)
throw new Exception("SweepAngle cannot be negative.");
_SweepAngle = value;
OnPropertyChangedEx("SweepAngle", Style.VisualChangeType.Layout);
}
}
}
#endregion
#region ToolTipText
/// <summary>
/// Gets or sets the text to use for the point ToolTip.
/// </summary>
[DefaultValue(null), Category("Label")]
[Description("Indicates the text to use for the point ToolTip.")]
[Editor(typeof(MultilineStringEditor), typeof(UITypeEditor))]
public string ToolTipText
{
get { return (_ToolTipText); }
set
{
if (value != _ToolTipText)
{
_ToolTipText = value;
OnPropertyChanged("ToolTipText");
}
}
}
#endregion
#region Visible
/// <summary>
/// Gets or sets whether the point is Visible.
/// </summary>
[DefaultValue(true), Category("Appearance")]
[Description("Indicates whether the point is Visible.")]
public override bool Visible
{
get { return (base.Visible); }
set
{
if (value != base.Visible)
{
base.Visible = value;
OnPropertyChangedEx("Visible", VisualChangeType.Recalc);
}
}
}
#endregion
#endregion
#region Internal properties
#region AngleMarginExx
internal double AngleMarginExx
{
get { return (_AngleMarginExx); }
set { _AngleMarginExx = value; }
}
#endregion
#region AngleMarginEx
internal double AngleMarginEx
{
get { UpdatePropertyCache(); return (_AngleMarginEx); }
set { _AngleMarginEx = value; }
}
#endregion
#region Bounds
internal Rectangle Bounds
{
get
{
Rectangle r = new Rectangle();
r.Location = _SliceCenter;
r.Inflate(OuterRadius, OuterRadius);
return (r);
}
}
#endregion
#region CharBounds
internal RectangleF[] CharBounds
{
get
{
VerifyLayoutUpdateCount();
return (_CharBounds);
}
set { _CharBounds = value; }
}
#endregion
#region HasExtent
internal bool HasExtent
{
get { return (TestState(States.HasExtent)); }
set { SetState(States.HasExtent, value); }
}
#endregion
#region InnerLabelClipped
internal bool InnerLabelClipped
{
get { return (TestState(States.InnerLabelClipped)); }
set { SetState(States.InnerLabelClipped, value); }
}
#endregion
#region InnerLabelDisplayed
internal bool InnerLabelDisplayed
{
get { return (TestState(States.InnerLabelDisplayed)); }
set { SetState(States.InnerLabelDisplayed, value); }
}
#endregion
#region InnerLabelOrientationEx
internal SliceLabelOrientation InnerLabelOrientationEx
{
get { UpdatePropertyCache(); return (_InnerLabelOrientationEx); }
set { _InnerLabelOrientationEx = value; }
}
#endregion
#region InnerSliceLabelEx
internal string InnerSliceLabelEx
{
get { UpdatePropertyCache(); return (_InnerSliceLabelEx); }
set { _InnerSliceLabelEx = value; }
}
#endregion
#region InscribedRect
internal Rectangle InscribedRect
{
get
{
VerifyLayoutUpdateCount();
return (_InscribedRect);
}
set
{
_InscribedRect = value;
InscribedRectValid = true;
}
}
#endregion
#region InscribedRectValid
internal bool InscribedRectValid
{
get
{
VerifyLayoutUpdateCount();
return (TestState(States.InscribedRectValid));
}
set
{
SetState(States.InscribedRectValid, value);
if (value == false)
_InscribedRect = Rectangle.Empty;
}
}
#endregion
#region IsDisplayable
internal bool IsDisplayable
{
get
{
if (Visible == false || IsEmpty == true)
return (false);
if (IsInOtherEx == false)
{
object item = Parent;
while (item != null)
{
if (item is PieSeriesPointCollection)
{
if (((PieSeriesPointCollection)item).IsOther == true)
{
IsInOtherEx = true;
break;
}
item = ((PieSeriesPointCollection)item).Parent;
}
else if (item is PieSeriesPoint)
{
if (((PieSeriesPoint)item).IsInOtherEx == true)
{
IsInOtherEx = true;
break;
}
item = ((PieSeriesPoint)item).Parent;
}
else
{
break;
}
}
}
return (IsInOtherEx == false);
}
}
#endregion
#region IsDisplayedEx
internal bool IsDisplayedEx
{
get
{
if (Visible == true)
{
if (ChartSeries != null)
{
PieChart pieChart = ChartSeries.Parent as PieChart;
if (pieChart != null)
{
ItemCheckAction ica = (pieChart != null)
? pieChart.Legend.ItemCheckAction : ItemCheckAction.ShowItem;
return ((ica == ItemCheckAction.None ||
(ShowCheckBoxInLegend == false || CheckedInLegend == true)));
}
}
}
return (false);
}
}
#endregion
#region IsInOtherEx
internal bool IsInOtherEx
{
get { return (TestState(States.IsInOtherEx)); }
set { SetState(States.IsInOtherEx, value); }
}
#endregion
#region IsOffset
internal bool IsOffset
{
get { return (TestState(States.IsOffset)); }
set { SetState(States.IsOffset, value); }
}
#endregion
#region IsEnabled
internal bool IsEnabled
{
get
{
PieRing pieRing = PieRing;
if (pieRing != null)
{
if (pieRing.IsEnabled == true)
return (pieRing.IsDisplayed);
}
return (false);
}
}
#endregion
#region LastPathBounds
internal Rectangle LastPathBounds
{
get { return (_LastPathBounds); }
set { _LastPathBounds = value; }
}
#endregion
#region MaxSlicesEx
internal int MaxSlicesEx
{
get { UpdatePropertyCache(); return (_MaxSlicesEx); }
set { _MaxSlicesEx = value; }
}
#endregion
#region MinExtentEx
internal int MinExtentEx
{
get { UpdatePropertyCache(); return (_MinExtentEx); }
set { _MinExtentEx = value; }
}
#endregion
#region MinPercentEx
internal double MinPercentEx
{
get { UpdatePropertyCache(); return (_MinPercentEx); }
set { _MinPercentEx = value; }
}
#endregion
#region OuterSliceLabelEx
internal string OuterSliceLabelEx
{
get { UpdatePropertyCache(); return (_OuterSliceLabelEx); }
set { _OuterSliceLabelEx = value; }
}
#endregion
#region PathBounds
internal Rectangle PathBounds
{
get { return (_PathBounds); }
set { _PathBounds = value; }
}
#endregion
#region PieLabel
internal PieLabel PieLabel
{
get { return (_PieLabel); }
set { _PieLabel = value; }
}
#endregion
#region ReferenceLineDisplayModeEx
internal PieRefLineDisplayMode ReferenceLineDisplayModeEx
{
get { UpdatePropertyCache(); return (_ReferenceLineDisplayModeEx); }
set { _ReferenceLineDisplayModeEx = value; }
}
#endregion
#region ReferenceLineDisplayOnTopEx
internal bool ReferenceLineDisplayOnTopEx
{
get
{
UpdatePropertyCache();
return (TestState(States.ReferenceLineDisplayOnTop));
}
set { SetState(States.ReferenceLineDisplayOnTop, value); }
}
#endregion
#region ReferenceLinesEx
internal List<PieReferenceLine> ReferenceLinesEx
{
get { UpdatePropertyCache(); return (_ReferenceLinesEx); }
set { _ReferenceLinesEx = value; }
}
#endregion
#region RenderCount
private int _RenderCount;
internal int RenderCount
{
get { return (_RenderCount); }
set { _RenderCount = value; }
}
#endregion
#region RingWeightEx
internal int RingWeightEx
{
get { UpdatePropertyCache(); return (_RingWeightEx); }
set { _RingWeightEx = value; }
}
#endregion
#region RootPsp
internal PieSeriesPoint RootPsp
{
get
{
if (_RootPsp == null)
_RootPsp = GetRootPsp();
return (_RootPsp);
}
}
#region GetRootPsp
private PieSeriesPoint GetRootPsp()
{
if (PieRing.RingLevel > 0)
{
PieSeriesPointCollection spc = Parent as PieSeriesPointCollection;
if (spc != null)
{
PieSeriesPoint psp = spc.Parent as PieSeriesPoint;
if (psp != null)
return (psp.RootPsp);
}
}
return (this);
}
#endregion
#endregion
#region ShowSliceWhiteSpaceEx
internal bool ShowSliceWhiteSpaceEx
{
get
{
UpdatePropertyCache();
return (TestState(States.ShowSliceWhiteSpaceEx));
}
set { SetState(States.ShowSliceWhiteSpaceEx, value); }
}
#endregion
#region SliceLabelCropModeEx
internal SliceLabelCropMode SliceLabelCropModeEx
{
get { UpdatePropertyCache(); return (_SliceLabelCropModeEx); }
set { _SliceLabelCropModeEx = value; }
}
#endregion
#region SliceLabelDisplayModeEx
internal SliceLabelDisplayMode SliceLabelDisplayModeEx
{
get { UpdatePropertyCache(); return (_SliceLabelDisplayModeEx); }
set { _SliceLabelDisplayModeEx = value; }
}
#endregion
#region SliceLabelVisibilityEx
internal SliceLabelVisibility SliceLabelVisibilityEx
{
get { UpdatePropertyCache(); return (_SliceLabelVisibilityEx); }
set { _SliceLabelVisibilityEx = value; }
}
#endregion
#region StartAngleEx
internal double StartAngleEx
{
get { return (_StartAngleEx); }
set { _StartAngleEx = value; }
}
#endregion
#region SweepAngleEx
internal double SweepAngleEx
{
get { return (_SweepAngleEx); }
set { _SweepAngleEx = value; }
}
#endregion
#region ToolTipTextEx
internal string ToolTipTextEx
{
get { UpdatePropertyCache(); return (_ToolTipTextEx); }
set { _ToolTipTextEx = value; }
}
#endregion
#region WordPosLines
internal List<WordPosLine> WordPosLines
{
get
{
VerifyLayoutUpdateCount();
return (_WordPosLines);
}
set { _WordPosLines = value; }
}
#endregion
#endregion
#region VerifyLayoutUpdateCount
private void VerifyLayoutUpdateCount()
{
PieSeries series = ChartSeries;
if (series != null)
{
ChartControl chartControl = series.ChartControl;
if (chartControl != null)
{
if (_LayoutUpdateCount != chartControl.LayoutUpdateCount)
{
_WordPosLines = null;
InscribedRectValid = false;
_LayoutUpdateCount = chartControl.LayoutUpdateCount;
}
}
}
}
#endregion
#region UpdatePropertyCache
private void UpdatePropertyCache()
{
if (ChartControl != null)
{
if (_LocalUpdateCount != ChartControl.GlobalUpdateCount)
{
PieSeriesPointCollection spc = Parent as PieSeriesPointCollection;
if (spc != null)
{
PieSeries pieSeries = this.ChartSeries;
PieChart pieChart = pieSeries.Parent as PieChart;
_AngleMarginEx = GetAngleMarginEx(pieChart, pieSeries, spc.Parent);
_InnerLabelOrientationEx = GetSliceLabelOrientationEx(pieChart, pieSeries, spc.Parent);
_InnerSliceLabelEx = GetInnerSliceLabelEx(pieChart, pieSeries, spc.Parent);
_MaxSlicesEx = GetMaxSlicesEx(pieChart, pieSeries, spc.Parent);
_MinExtentEx = GetMinExtentEx(pieChart, pieSeries, spc.Parent);
_MinPercentEx = GetMinPercentEx(pieChart, pieSeries, spc.Parent);
_OuterSliceLabelEx = GetOuterSliceLabelEx(pieChart, pieSeries, spc.Parent);
_ReferenceLineDisplayModeEx = GetReferenceLineDisplayModeEx(pieChart, pieSeries, spc.Parent);
_ReferenceLinesEx = GetReferenceLinesEx(pieChart, pieSeries, spc.Parent);
_RingWeightEx = GetRingWeightEx(pieChart, pieSeries, spc.Parent);
SetState(States.ReferenceLineDisplayOnTop, GetReferenceLineDisplayOnTopEx(pieChart, pieSeries, spc.Parent));
SetState(States.ShowSliceWhiteSpaceEx, GetShowSliceWhiteSpaceEx(pieChart, pieSeries, spc.Parent));
_SliceLabelCropModeEx = GetSliceLabelCropModeEx(pieChart, pieSeries, spc.Parent);
_SliceLabelDisplayModeEx = GetSliceLabelDisplayModeEx(pieChart, pieSeries, spc.Parent);
_SliceLabelVisibilityEx = GetSliceLabelVisibilityEx(pieChart, pieSeries, spc.Parent);
_ToolTipTextEx = GetToolTipTextEx(pieChart, pieSeries, spc.Parent);
}
_LocalUpdateCount = ChartControl.GlobalUpdateCount;
}
}
}
#region GetAngleMarginEx
private double GetAngleMarginEx(
PieChart pieChart, PieSeries pieSeries, object item)
{
PieSeriesPoint psp = item as PieSeriesPoint;
while (psp != null)
{
if (double.IsNaN(psp.SubSliceVisualLayout.AngleMargin) == false)
return (psp.SubSliceVisualLayout.AngleMargin);
psp = GetParentPsp(psp);
}
if (double.IsNaN(pieSeries.SubSliceVisualLayout.AngleMargin) == false)
return (pieSeries.SubSliceVisualLayout.AngleMargin);
if (double.IsNaN(pieChart.SubSliceVisualLayout.AngleMargin) == false)
return (pieChart.SubSliceVisualLayout.AngleMargin);
return (0);
}
#endregion
#region GetInnerSliceLabelEx
private string GetInnerSliceLabelEx(
PieChart pieChart, PieSeries pieSeries, object item)
{
CharBounds = null;
if (InnerSliceLabel != null)
return (InnerSliceLabel);
PieSeriesPoint psp = item as PieSeriesPoint;
while (psp != null)
{
if (psp.SubSliceVisualLayout.InnerSliceLabel != null)
return (psp.SubSliceVisualLayout.InnerSliceLabel);
psp = GetParentPsp(psp);
}
if (pieSeries.SubSliceVisualLayout.InnerSliceLabel != null)
return (pieSeries.SubSliceVisualLayout.InnerSliceLabel);
if (pieChart.SubSliceVisualLayout.InnerSliceLabel != null)
return (pieChart.SubSliceVisualLayout.InnerSliceLabel);
return ("{X}");
}
#endregion
#region GetMaxSlicesEx
private int GetMaxSlicesEx(
PieChart pieChart, PieSeries pieSeries, object item)
{
PieSeriesPoint psp = item as PieSeriesPoint;
while (psp != null)
{
if (psp.SubSliceVisualLayout.MaxSlices >= 0)
return (psp.SubSliceVisualLayout.MaxSlices);
psp = GetParentPsp(psp);
}
if (pieSeries.SubSliceVisualLayout.MaxSlices >= 0)
return (pieSeries.SubSliceVisualLayout.MaxSlices);
if (pieChart.SubSliceVisualLayout.MaxSlices >= 0)
return (pieChart.SubSliceVisualLayout.MaxSlices);
return (100);
}
#endregion
#region GetMinExtentEx
private int GetMinExtentEx(
PieChart pieChart, PieSeries pieSeries, object item)
{
PieSeriesPoint psp = item as PieSeriesPoint;
while (psp != null)
{
if (psp.SubSliceVisualLayout.MinExtent >= 0)
return (psp.SubSliceVisualLayout.MinExtent);
psp = GetParentPsp(psp);
}
if (pieSeries.SubSliceVisualLayout.MinExtent >= 0)
return (pieSeries.SubSliceVisualLayout.MinExtent);
if (pieChart.SubSliceVisualLayout.MinExtent >= 0)
return (pieChart.SubSliceVisualLayout.MinExtent);
return (0);
}
#endregion
#region GetMinPercentEx
private double GetMinPercentEx(
PieChart pieChart, PieSeries pieSeries, object item)
{
PieSeriesPoint psp = item as PieSeriesPoint;
while (psp != null)
{
if (double.IsNaN(psp.SubSliceVisualLayout.MinPercent) == false)
return (psp.SubSliceVisualLayout.MinPercent);
psp = GetParentPsp(psp);
}
if (double.IsNaN(pieSeries.SubSliceVisualLayout.MinPercent) == false)
return (pieSeries.SubSliceVisualLayout.MinPercent);
if (double.IsNaN(pieChart.SubSliceVisualLayout.MinPercent) == false)
return (pieChart.SubSliceVisualLayout.MinPercent);
return (.04d);
}
#endregion
#region GetOuterSliceLabelEx
private string GetOuterSliceLabelEx(
PieChart pieChart, PieSeries pieSeries, object item)
{
if (OuterSliceLabel != null)
return (OuterSliceLabel);
PieSeriesPoint psp = item as PieSeriesPoint;
while (psp != null)
{
if (psp.SubSliceVisualLayout.OuterSliceLabel != null)
return (psp.SubSliceVisualLayout.OuterSliceLabel);
psp = GetParentPsp(psp);
}
if (pieSeries.SubSliceVisualLayout.OuterSliceLabel != null)
return (pieSeries.SubSliceVisualLayout.OuterSliceLabel);
if (pieChart.SubSliceVisualLayout.OuterSliceLabel != null)
return (pieChart.SubSliceVisualLayout.OuterSliceLabel);
return ("{X}");
}
#endregion
#region GetReferenceLineDisplayModeEx
private PieRefLineDisplayMode GetReferenceLineDisplayModeEx(
PieChart pieChart, PieSeries pieSeries, object item)
{
PieSeriesPoint psp = item as PieSeriesPoint;
while (psp != null)
{
if (psp.SubSliceVisualLayout.ReferenceLineDisplayMode != PieRefLineDisplayMode.NotSet)
return (psp.SubSliceVisualLayout.ReferenceLineDisplayMode);
psp = GetParentPsp(psp);
}
if (pieSeries.SubSliceVisualLayout.ReferenceLineDisplayMode != PieRefLineDisplayMode.NotSet)
return (pieSeries.SubSliceVisualLayout.ReferenceLineDisplayMode);
if (pieChart.SubSliceVisualLayout.ReferenceLineDisplayMode != PieRefLineDisplayMode.NotSet)
return (pieChart.SubSliceVisualLayout.ReferenceLineDisplayMode);
return (PieRefLineDisplayMode.None);
}
#endregion
#region GetReferenceLineDisplayOnTopEx
private bool GetReferenceLineDisplayOnTopEx(
PieChart pieChart, PieSeries pieSeries, object item)
{
PieSeriesPoint psp = item as PieSeriesPoint;
while (psp != null)
{
if (psp.SubSliceVisualLayout.ReferenceLineDisplayOnTop != Tbool.NotSet)
return (psp.SubSliceVisualLayout.ReferenceLineDisplayOnTop == Tbool.True);
psp = GetParentPsp(psp);
}
if (pieSeries.SubSliceVisualLayout.ReferenceLineDisplayOnTop != Tbool.NotSet)
return (pieSeries.SubSliceVisualLayout.ReferenceLineDisplayOnTop == Tbool.True);
return (pieChart.SubSliceVisualLayout.ReferenceLineDisplayOnTop != Tbool.False);
}
#endregion
#region GetReferenceLinesEx
private List<PieReferenceLine> GetReferenceLinesEx(
PieChart pieChart, PieSeries pieSeries, object item)
{
List<PieReferenceLine> lines = new List<PieReferenceLine>();
PieSeriesPoint psp = item as PieSeriesPoint;
while (psp != null)
{
if (psp.SubSliceVisualLayout._ReferenceLines != null)
AddReferenceLines(lines, psp.SubSliceVisualLayout.ReferenceLines);
psp = GetParentPsp(psp);
}
if (pieSeries.SubSliceVisualLayout._ReferenceLines != null)
AddReferenceLines(lines, pieSeries.SubSliceVisualLayout.ReferenceLines);
if (pieChart.SubSliceVisualLayout._ReferenceLines != null)
AddReferenceLines(lines, pieChart.SubSliceVisualLayout.ReferenceLines);
return (lines);
}
#region AddReferenceLines
private void AddReferenceLines(
List<PieReferenceLine> lines, PieReferenceLineCollection rlc)
{
foreach (PieReferenceLine line in rlc)
lines.Add(line);
}
#endregion
#endregion
#region GetRingWeightEx
private int GetRingWeightEx(
PieChart pieChart, PieSeries pieSeries, object item)
{
PieSeriesPoint psp = item as PieSeriesPoint;
while (psp != null)
{
if (psp.SubSliceVisualLayout.RingWeight >= 0)
return (psp.SubSliceVisualLayout.RingWeight);
psp = GetParentPsp(psp);
}
if (pieSeries.SubSliceVisualLayout.RingWeight >= 0)
return (pieSeries.SubSliceVisualLayout.RingWeight);
if (pieChart.SubSliceVisualLayout.RingWeight >= 0)
return (pieChart.SubSliceVisualLayout.RingWeight);
return (100);
}
#endregion
#region GetShowSliceWhiteSpaceEx
private bool GetShowSliceWhiteSpaceEx(
PieChart pieChart, PieSeries pieSeries, object item)
{
PieSeriesPoint psp = item as PieSeriesPoint;
while (psp != null)
{
if (psp.SubSliceVisualLayout.ShowSliceWhiteSpace != Tbool.NotSet)
return (psp.SubSliceVisualLayout.ShowSliceWhiteSpace == Tbool.True);
psp = GetParentPsp(psp);
}
if (pieSeries.SubSliceVisualLayout.ShowSliceWhiteSpace != Tbool.NotSet)
return (pieSeries.SubSliceVisualLayout.ShowSliceWhiteSpace == Tbool.True);
return (pieChart.SubSliceVisualLayout.ShowSliceWhiteSpace == Tbool.True);
}
#endregion
#region GetSliceLabelCropModeEx
private SliceLabelCropMode GetSliceLabelCropModeEx(
PieChart pieChart, PieSeries pieSeries, object item)
{
PieSeriesPoint psp = item as PieSeriesPoint;
while (psp != null)
{
if (psp.SubSliceVisualLayout.SliceLabelCropMode != SliceLabelCropMode.NotSet)
return (psp.SubSliceVisualLayout.SliceLabelCropMode);
psp = GetParentPsp(psp);
}
if (pieSeries.SubSliceVisualLayout.SliceLabelCropMode != SliceLabelCropMode.NotSet)
return (pieSeries.SubSliceVisualLayout.SliceLabelCropMode);
if (pieChart.SubSliceVisualLayout.SliceLabelCropMode != SliceLabelCropMode.NotSet)
return (pieChart.SubSliceVisualLayout.SliceLabelCropMode);
return (SliceLabelCropMode.Clip);
}
#endregion
#region GetSliceLabelDisplayModeEx
private SliceLabelDisplayMode GetSliceLabelDisplayModeEx(
PieChart pieChart, PieSeries pieSeries, object item)
{
PieSeriesPoint psp = item as PieSeriesPoint;
while (psp != null)
{
if (psp.SubSliceVisualLayout.SliceLabelDisplayMode != SliceLabelDisplayMode.NotSet)
return (psp.SubSliceVisualLayout.SliceLabelDisplayMode);
psp = GetParentPsp(psp);
}
if (pieSeries.SubSliceVisualLayout.SliceLabelDisplayMode != SliceLabelDisplayMode.NotSet)
return (pieSeries.SubSliceVisualLayout.SliceLabelDisplayMode);
if (pieChart.SubSliceVisualLayout.SliceLabelDisplayMode != SliceLabelDisplayMode.NotSet)
return (pieChart.SubSliceVisualLayout.SliceLabelDisplayMode);
return (SliceLabelDisplayMode.InnerAndOuter);
}
#endregion
#region GetSliceLabelOrientationEx
private SliceLabelOrientation GetSliceLabelOrientationEx(
PieChart pieChart, PieSeries pieSeries, object item)
{
PieSeriesPoint psp = item as PieSeriesPoint;
while (psp != null)
{
if (psp.SubSliceVisualLayout.InnerLabelOrientation != SliceLabelOrientation.NotSet)
return (psp.SubSliceVisualLayout.InnerLabelOrientation);
psp = GetParentPsp(psp);
}
if (pieSeries.SubSliceVisualLayout.InnerLabelOrientation != SliceLabelOrientation.NotSet)
return (pieSeries.SubSliceVisualLayout.InnerLabelOrientation);
if (pieChart.SubSliceVisualLayout.InnerLabelOrientation != SliceLabelOrientation.NotSet)
return (pieChart.SubSliceVisualLayout.InnerLabelOrientation);
return (SliceLabelOrientation.Adaptive);
}
#endregion
#region GetSliceLabelVisibilityEx
private SliceLabelVisibility GetSliceLabelVisibilityEx(
PieChart pieChart, PieSeries pieSeries, object item)
{
PieSeriesPoint psp = item as PieSeriesPoint;
while (psp != null)
{
if (psp.SubSliceVisualLayout.SliceLabelVisibility != SliceLabelVisibility.NotSet)
return (psp.SubSliceVisualLayout.SliceLabelVisibility);
psp = GetParentPsp(psp);
}
if (pieSeries.SubSliceVisualLayout.SliceLabelVisibility != SliceLabelVisibility.NotSet)
return (pieSeries.SubSliceVisualLayout.SliceLabelVisibility);
if (pieChart.SubSliceVisualLayout.SliceLabelVisibility != SliceLabelVisibility.NotSet)
return (pieChart.SubSliceVisualLayout.SliceLabelVisibility);
return (SliceLabelVisibility.NotSet);
}
#endregion
#region GetToolTipTextEx
private string GetToolTipTextEx(
PieChart pieChart, PieSeries pieSeries, object item)
{
PieSeriesPoint psp = item as PieSeriesPoint;
while (psp != null)
{
if (psp.SubSliceVisualLayout.ToolTipText != null)
return (psp.SubSliceVisualLayout.ToolTipText);
psp = GetParentPsp(psp);
}
if (pieSeries.SubSliceVisualLayout.ToolTipText != null)
return (pieSeries.SubSliceVisualLayout.ToolTipText);
if (pieChart.SubSliceVisualLayout.ToolTipText != null)
return (pieChart.SubSliceVisualLayout.ToolTipText);
return ("{x}");
}
#endregion
#region GetParentPsp
private PieSeriesPoint GetParentPsp(PieSeriesPoint psp)
{
PieSeriesPointCollection spc = psp.Parent as PieSeriesPointCollection;
return (spc != null) ? spc.Parent as PieSeriesPoint : null;
}
#endregion
#endregion
#region GetRayEndPoint
internal Point GetRayEndPoint(double angle, double radius)
{
Point pt = SliceCenter;
double radians = MathHelper.ToRadians(angle);
pt.X += (int)(Math.Cos(radians) * radius);
pt.Y += (int)(Math.Sin(radians) * radius);
return (pt);
}
#endregion
#region GetLabelText
internal string GetLabelText(string pattern)
{
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(ProcessSliceLabelFmt(ma.Value));
index = ma.Index + ma.Length;
}
if (index < pattern.Length)
sb.Append(pattern.Substring(index));
return (sb.ToString());
}
#region ProcessSliceLabelFmt
/// "AVG" "A" - Average (angular values).
/// "PCT" "P" - Percent of pie (angular values) - (.025 yields "2.5 %").
/// "TOT" "T" - Total of all values (angluar values).
/// "VAL" "V" - Value percent of pie (angular value) - (.025 yields ".025").
///
/// "AVGX" "AX" - Average (extent/radial values).
/// "PCTX" "PX" - Percent of pie (extent values) - (.025 yields "2.5 %").
/// "TOTX" "TX" - Total of all values (extent values).
/// "VALX" "VX" - Value percent of pie (extent value) - (.025 yields ".025").
///
/// "S" "SNAME" - Series name.
/// "X" - ValueX.
/// "Y", "Y0", "Yn" - ValueY values (where 'n' is index value).
///
/// Use: {format[:specifier]}
private string ProcessSliceLabelFmt(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
{
PieSeriesPointCollection spc = Parent as PieSeriesPointCollection;
switch (placeHolder)
{
case "A":
case "AVG":
if (spc != null)
return (GetSliceLabelText(spc.PieAverage, formatSpecifier));
break;
case "AX":
case "AVGX":
if (spc != null)
return (GetSliceLabelText(spc.PieAverageExtent, formatSpecifier));
break;
case "N":
case "NAME":
if (string.IsNullOrEmpty(formatSpecifier) == false)
return (String.Format(formatSpecifier, Name));
return (Name);
case "P":
case "PCT":
if (string.IsNullOrEmpty(formatSpecifier) == false)
return (SliceValue.ToString(formatSpecifier));
return (GetSliceLabelText(SliceValue, "P"));
case "PX":
case "PCTX":
if (string.IsNullOrEmpty(formatSpecifier) == false)
return (SliceExtent.ToString(formatSpecifier));
return (GetSliceLabelText(SliceExtent, "P"));
case "S":
case "SNAME":
string sname = ChartSeries != null ? ChartSeries.Name : "";
if (string.IsNullOrEmpty(formatSpecifier) == false)
return (String.Format(formatSpecifier, sname));
return (sname);
case "T":
case "TOTA":
if (spc != null)
return (GetSliceLabelText(spc.PieTotal, formatSpecifier));
break;
case "TX":
case "TOTX":
if (spc != null)
return (GetSliceLabelText(spc.PieTotalExtent, formatSpecifier));
break;
case "V":
case "VAL":
return (GetSliceLabelText(SliceValue, formatSpecifier));
case "VX":
case "VALX":
return (GetSliceLabelText(SliceExtent, formatSpecifier));
case "X":
return (GetSliceLabelText(ValueX, formatSpecifier));
case "Y":
case "Y0":
if (ValueY != null && ValueY.Length > 0)
return (GetSliceLabelText(ValueY[0], formatSpecifier));
return ("");
default:
if (placeHolder.StartsWith("Y") == true)
{
int index = int.Parse(placeHolder.Substring(1));
if (ValueY != null && ValueY.Length > index)
return (GetSliceLabelText(ValueY[index], formatSpecifier));
}
return (s);
}
}
catch
{
}
return (s);
}
#region GetSliceLabelText
private string GetSliceLabelText(object value, string format)
{
if (value is string)
{
if (string.IsNullOrEmpty(format) == true)
return ((string)value);
return (String.Format(format, value));
}
else
{
double d = Convert.ToDouble(value);
if (string.IsNullOrEmpty(format) == false)
return (d.ToString(format));
return (d.ToString("F3"));
}
}
#endregion
#endregion
#endregion
#region Style handling
#region GetEffectiveSliceStyle
public ChartSliceVisualStyle
GetEffectiveSliceStyle(PieChart pieChart, PieSeries series)
{
StyleState state = StyleState.Default;
if (series.IsHighLightedPsp(pieChart, this) == true)
state |= StyleState.MouseOver;
if (IsSelected == true)
state |= StyleState.Selected;
ChartSliceVisualStyle estyle = EffectiveSliceStyles[state];
if (_WordPosLines != null)
{
if (_LastEffectiveStyle != null)
{
if (EqualFonts(estyle.SliceInnerLabelStyle.Font,
_LastEffectiveStyle.SliceInnerLabelStyle.Font) == false)
{
_CharBounds = null;
_WordPosLines = null;
}
}
_LastEffectiveStyle = estyle;
}
return (estyle);
}
#region EqualFonts
private bool EqualFonts(Font font1, Font font2)
{
if (font1 == null || font2 == null)
return (false);
return (font1.Name == font2.Name &&
font1.SizeInPoints == font2.SizeInPoints &&
font1.Style == font2.Style);
}
#endregion
#endregion
#region ApplyStyles
public void ApplyStyles(BaseVisualStyle style)
{
}
public void ApplyStyles(BaseVisualStyle style, StyleType cs)
{
ChartSliceVisualStyle sstyle = style as ChartSliceVisualStyle;
if (sstyle != null)
{
PieSeriesPointCollection spc = Parent as PieSeriesPointCollection;
PieSeries series = ChartSeries;
if (IsOther == true)
{
ApplyOtherParentStyles(sstyle, cs, series.Parent as ChartContainer);
sstyle.ApplyStyle(series.SubSliceVisualLayout.OtherSliceVisualStyles[cs]);
ApplyOtherParentPspStyle(sstyle, cs, this);
}
else
{
ApplyParentStyles(sstyle, cs, series.Parent as ChartContainer);
sstyle.ApplyStyle(series.SubSliceVisualLayout.SliceVisualStyles[cs]);
ApplyParentPspStyle(sstyle, cs, this);
}
sstyle.ApplyStyle(SliceVisualStyles[cs]);
}
}
#region ApplyOtherParentStyles
private void ApplyOtherParentStyles(
ChartSliceVisualStyle sstyle, StyleType cs, ChartContainer item)
{
if (item != null)
{
ApplyOtherParentStyles(sstyle, cs, item.Parent as ChartContainer);
ChartPanel panel = item as ChartPanel;
if (panel != null)
{
sstyle.ApplyStyle(panel.DefaultVisualStyles.OtherSliceVisualStyles[cs]);
}
else
{
PieChart pieChart = item as PieChart;
if (pieChart != null)
sstyle.ApplyStyle(pieChart.SubSliceVisualLayout.OtherSliceVisualStyles[cs]);
}
}
else
{
ChartControl chartControl = ChartControl;
if (chartControl != null)
{
sstyle.ApplyStyle(chartControl.BaseVisualStyles.OtherSliceVisualStyles[cs]);
sstyle.ApplyStyle(chartControl.DefaultVisualStyles.OtherSliceVisualStyles[cs]);
}
}
}
#endregion
#region ApplyOtherParentPspStyle
private void ApplyOtherParentPspStyle(
ChartSliceVisualStyle sstyle, StyleType cs, PieSeriesPoint psp)
{
psp = GetParentPsp(psp);
if (psp != null)
{
ApplyOtherParentPspStyle(sstyle, cs, psp);
sstyle.ApplyStyle(psp.SubSliceVisualLayout.OtherSliceVisualStyles[cs]);
}
}
#endregion
#region ApplyParentStyles
private void ApplyParentStyles(
ChartSliceVisualStyle sstyle, StyleType cs, ChartContainer item)
{
if (item != null)
{
ApplyParentStyles(sstyle, cs, item.Parent as ChartContainer);
if (item is PieChart)
sstyle.ApplyStyle(((PieChart)item).SubSliceVisualLayout.SliceVisualStyles[cs]);
if (item is ChartPanel)
sstyle.ApplyStyle(((ChartPanel)item).DefaultVisualStyles.SliceVisualStyles[cs]);
}
else
{
ChartControl chartControl = ChartControl;
if (chartControl != null)
{
sstyle.ApplyStyle(ChartControl.BaseVisualStyles.SliceVisualStyles[cs]);
sstyle.ApplyStyle(ChartControl.DefaultVisualStyles.SliceVisualStyles[cs]);
}
}
}
#endregion
#region ApplyParentPspStyle
private void ApplyParentPspStyle(
ChartSliceVisualStyle sstyle, StyleType cs, PieSeriesPoint psp)
{
psp = GetParentPsp(psp);
if (psp != null)
{
ApplyParentPspStyle(sstyle, cs, psp);
sstyle.ApplyStyle(psp.SubSliceVisualLayout.SliceVisualStyles[cs]);
}
}
#endregion
#endregion
#region ApplyDefaults
public void ApplyDefaults(BaseVisualStyle style, StyleType styleType)
{
ChartSliceVisualStyle sstyle = style as ChartSliceVisualStyle;
if (sstyle != null)
{
HatchFillType hatch = HatchFillType.LightUpwardDiagonal;
switch (styleType)
{
case StyleType.Default:
if (sstyle.Background.IsEmpty == true)
sstyle.Background = new Background(DefaultPaletteColor);
if (sstyle.WhiteSpaceBackground.IsEmpty == true)
sstyle.WhiteSpaceBackground = new Background(Color.FromArgb(100, DefaultPaletteColor));
if (sstyle.WhiteSpaceBorder.LinePattern == LinePattern.NotSet)
sstyle.WhiteSpaceBorder.LinePattern = LinePattern.Solid;
break;
case StyleType.MouseOver:
if (sstyle.Background.IsEmpty == true)
sstyle.Background = new Background(ControlPaint.Light(DefaultPaletteColor));
if (sstyle.WhiteSpaceBackground.IsEmpty == true)
sstyle.WhiteSpaceBackground = new Background(Color.FromArgb(50, DefaultPaletteColor));
if (sstyle.WhiteSpaceBorder.LinePattern == LinePattern.NotSet)
sstyle.WhiteSpaceBorder.LinePattern = LinePattern.Solid;
break;
case StyleType.Selected:
if (sstyle.Background.IsEmpty == true)
{
sstyle.Background = new Background(Color.White, DefaultPaletteColor);
sstyle.Background.HatchFillType = hatch;
}
if (sstyle.Border.LineWidth < 0)
sstyle.Border.LineWidth = 2;
if (sstyle.WhiteSpaceBackground.IsEmpty == true)
{
sstyle.WhiteSpaceBackground = new Background(Color.White, Color.FromArgb(100, DefaultPaletteColor));
sstyle.WhiteSpaceBackground.HatchFillType = hatch;
}
if (sstyle.WhiteSpaceBorder.LineWidth < 0)
sstyle.WhiteSpaceBorder.LineWidth = 2;
break;
case StyleType.SelectedMouseOver:
if (sstyle.Background.IsEmpty == true)
{
sstyle.Background = new Background(Color.White, ControlPaint.Light(DefaultPaletteColor));
sstyle.Background.HatchFillType = hatch;
}
if (sstyle.Border.LineWidth < 0)
sstyle.Border.LineWidth = 2;
if (sstyle.WhiteSpaceBackground.IsEmpty == true)
{
sstyle.WhiteSpaceBackground = new Background(Color.White, Color.FromArgb(50, DefaultPaletteColor));
sstyle.WhiteSpaceBackground.HatchFillType = hatch;
}
if (sstyle.WhiteSpaceBorder.LineWidth < 0)
sstyle.WhiteSpaceBorder.LineWidth = 2;
break;
}
if (sstyle.Border.LineColor.IsEmpty == true)
sstyle.Border.LineColor = DefaultPaletteColor;
if (sstyle.WhiteSpaceBorder.LineColor.IsEmpty == true)
sstyle.WhiteSpaceBorder.LineColor = DefaultPaletteColor;
if (sstyle.ExtentAverageRefLineStyle.LineColor.IsEmpty == true)
sstyle.ExtentAverageRefLineStyle.LineColor = Color.DimGray;
if (sstyle.ExtentMinRefLineStyle.LineColor.IsEmpty == true)
sstyle.ExtentMinRefLineStyle.LineColor = Color.DimGray;
if (sstyle.ExtentMaxRefLineStyle.LineColor.IsEmpty == true)
sstyle.ExtentMaxRefLineStyle.LineColor = Color.DimGray;
if (sstyle.ExtentOuterRefLineStyle.LineColor.IsEmpty == true)
sstyle.ExtentOuterRefLineStyle.LineColor = Color.DimGray;
if (sstyle.SliceOuterLabelStyle.TextColor.IsEmpty == true)
sstyle.SliceOuterLabelStyle.TextColor = DefaultPaletteColor;
sstyle.ApplyDefaults();
}
}
#endregion
#region GetElementStyle
public virtual void GetElementStyle(
IEffectiveStyle chartElement, StyleType styleType, ref BaseVisualStyle style)
{
ChartControl chartControl = ChartControl;
if (chartControl != null)
chartControl.DoGetPieSeriesPointStyleEvent(this, styleType, ref style);
}
#endregion
#region ChartControl
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public ChartControl ChartControl
{
get
{
if (_ChartControl == null)
{
if (ChartSeries != null)
_ChartControl = ChartSeries.ChartControl;
}
return (_ChartControl);
}
}
#endregion
#region ClearEffectiveStyles
protected void ClearEffectiveStyles()
{
_EffectiveSliceStyles.InvalidateStyles();
}
#endregion
#region OnStyleChanged
protected virtual void OnStyleChanged(string property,
INotifyPropertyChanged oldValue, INotifyPropertyChanged newValue)
{
StyleChangeHandler(oldValue, newValue);
OnPropertyChanged(property);
}
#endregion
#region StyleChangeHandler
protected void StyleChangeHandler(
INotifyPropertyChanged oldValue, INotifyPropertyChanged newValue)
{
if (oldValue != null)
oldValue.PropertyChanged -= StyleChanged;
if (newValue != null)
newValue.PropertyChanged += StyleChanged;
}
#region StyleChanged
/// <summary>
/// Occurs when one of element visual styles has property changes.
/// Default implementation invalidates visual appearance of element.
/// </summary>
/// <param name="sender">VisualStyle that changed.</param>
/// <param name="e">Event arguments.</param>
protected void StyleChanged(object sender, PropertyChangedEventArgs e)
{
VisualChangeType changeType = ((VisualPropertyChangedEventArgs)e).ChangeType;
PieSeries series = ChartSeries;
if (series != null)
{
if (series.ChartControl != null)
series.ChartControl.GlobalUpdateCount++;
if (changeType == VisualChangeType.Layout)
series.InvalidateLayout();
else
series.InvalidateRender();
}
}
#endregion
#endregion
#endregion
#region ILegendItem
#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();
StyleChangeHandler(null, _ChartLegendItemVisualStyles);
}
return (_ChartLegendItemVisualStyles);
}
set
{
if (_ChartLegendItemVisualStyles != value)
{
ChartLegendItemVisualStyles oldValue = _ChartLegendItemVisualStyles;
_ChartLegendItemVisualStyles = value;
OnStyleChanged("ChartLegendItemVisualStyles", oldValue, value);
if (oldValue != null)
oldValue.Dispose();
}
}
}
#endregion
#region CheckedInLegend
/// <summary>
/// Gets or sets whether the item is checked in the Legend.
/// </summary>
[DefaultValue(true), Category("Legend")]
[Description("Indicates whether the item is checked in the Legend.")]
public bool CheckedInLegend
{
get { return (TestState(States.CheckedInLegend)); }
set
{
if (value != CheckedInLegend)
{
SetState(States.CheckedInLegend, value);
if (LegendItem != null)
LegendItem.UpdateCheckState();
OnPropertyChangedEx("CheckedInLegend", VisualChangeType.Layout);
}
}
}
#endregion
#region ShowCheckBoxInLegend
/// <summary>
/// Gets or sets whether a checkbox for the item is shown in the Legend.
/// </summary>
[DefaultValue(false), Category("Legend")]
[Description("Indicates whether a checkbox for the item 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 item is shown in the Legend.
/// </summary>
[DefaultValue(true), Category("Legend")]
[Description("Indicates whether the item 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 item Line is shown in parent Legend(s).
/// </summary>
[DefaultValue(true), Category("Legend")]
[Description("Indicates whether the item Line 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 item Marker is shown in the Legend.
/// </summary>
[DefaultValue(true), Category("Legend")]
[Description("Indicates whether the item 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
{
if (_LegendItem == null)
{
_LegendItem = new ChartLegendItem();
_LegendItem.Name = (ValueX != null ? ValueX.ToString() : "");
if (string.IsNullOrEmpty(_LegendItem.Name) == true)
_LegendItem.Name = "(Psp)";
_LegendItem.ChartItems.Add(this);
}
return (_LegendItem);
}
internal set { _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.")]
[NotifyParentProperty(true)]
public string LegendText
{
get { return (_LegendText); }
set
{
if (value != _LegendText)
{
_LegendText = value;
OnPropertyChangedEx("LegendText", Style.VisualChangeType.Layout);
}
}
}
#endregion
#region GetLegendItem
/// <summary>
/// Creates the LegendItem for the item.
/// </summary>
/// <returns></returns>
public ChartLegendItem GetLegendItem()
{
ChartLegendItem item = LegendItem;
if (ShowInLegend == true)
{
item.CheckState = (CheckedInLegend == true)
? CheckState.Checked : CheckState.Unchecked;
item.ItemText = LegendText;
item.IsEnabled = IsEnabled;
}
return (item);
}
#endregion
#region GetLegendItems
/// <summary>
/// Creates a list of legend items associated with
/// the item.
/// </summary>
/// <returns></returns>
public List<ChartLegendItem> GetLegendItems()
{
List<ChartLegendItem> list = null;
ChartLegendItem litem = GetLegendItem();
if (litem != null)
{
list = new List<ChartLegendItem>(1);
list.Add(litem);
}
return (list);
}
#endregion
#region GetLegendItemColor
/// <summary>
/// Gets the default color associated with the legend item.
/// </summary>
/// <returns></returns>
public Color GetLegendItemColor()
{
ChartSliceVisualStyle sstyle = EffectiveSliceStyles[StyleState.Default];
Color color = sstyle.Background.Color1;
if (color.IsEmpty == false)
return (color);
return (Color.DimGray);
}
#endregion
#region RenderLegendItemMarker
/// <summary>
/// Renders the Legend item Marker.
/// </summary>
/// <param name="g"></param>
/// <param name="litem"></param>
/// <param name="style"></param>
public void RenderLegendItemMarker(Graphics g,
ChartLegendItem litem, ChartLegendItemVisualStyle style)
{
ChartSliceVisualStyle sstyle = EffectiveSliceStyles[StyleState.Default];
Rectangle r = litem.MarkerBounds;
r.Inflate(-1, -1);
g.SmoothingMode = SmoothingMode.AntiAlias;
using (GraphicsPath path = new GraphicsPath())
{
Point pt = new Point(r.Right - 2, r.Bottom - 2);
r.Height += (r.Height - 4);
r.Width += (r.Width - 4);
path.AddArc(r, 180, 90);
path.AddLine(pt, pt);
path.CloseFigure();
if (IsEnabled == true)
{
if (sstyle.Background.IsEmpty == true)
{
g.FillPath(Brushes.LightPink, path);
}
else
{
using (Brush br = sstyle.Background.GetBrush(r))
g.FillPath(br, path);
if (sstyle.Background.Color1.IsEmpty == false)
{
using (Pen pen = new Pen(sstyle.Background.Color1))
g.DrawPath(pen, path);
}
}
}
else
{
Background back = style.DisabledMarkerBackground;
if (back.IsEmpty == true)
{
using (Brush br = new SolidBrush(Color.LightGray))
g.FillPath(br, path);
}
else
{
using (Brush br = back.GetBrush(r))
g.FillPath(br, path);
if (back.Color1.IsEmpty == false)
{
using (Pen pen = new Pen(sstyle.Background.Color1))
g.DrawPath(pen, path);
}
}
}
}
}
#endregion
#region TrackLegendItem
/// <summary>
/// Gets whether legend item tracking is enabled.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool TrackLegendItem
{
get
{
if (ChartSeries != null)
return (ChartSeries.TrackLegendItem);
return (false);
}
}
#endregion
#region FormatItemText
/// <summary>
/// Formats the provided item text.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public string FormatItemText(string text)
{
return (GetLabelText(text));
}
#endregion
#endregion
#region States
[Flags]
private enum States : uint
{
AllowDetach = (1U << 0),
AllowSelect = (1U << 1),
Detached = (1U << 2),
Selected = (1U << 3),
IsOther = (1U << 4),
IsInOther = (1U << 5),
IsInOtherEx = (1U << 6),
InnerLabelClipped = (1U << 7),
InnerLabelDisplayed = (1U << 8),
IsOffset = (1U << 9),
InscribedRectValid = (1 << 10),
CheckedInLegend = (1U << 11),
ShowInLegend = (1U << 12),
ShowInParentLegend = (1U << 13),
ShowCheckBoxInLegend = (1U << 14),
ShowMarkerInLegend = (1U << 15),
ReferenceLineDisplayOnTop = (1U << 16),
ShowSliceWhiteSpaceEx = (1U << 17),
HasExtent = (1U << 18),
}
#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 Copy/CopyTo
/// <summary>
/// Creates a copy of the PieSeriesPoint
/// </summary>
/// <returns></returns>
public new PieSeriesPoint Copy()
{
PieSeriesPoint copy = new PieSeriesPoint(ValueX, 0);
CopyTo(copy);
return (copy);
}
/// <summary>
/// Copies the item data to the given PieSeriesPoint.
/// </summary>
/// <param name="sp"></param>
public void CopyTo(PieSeriesPoint c)
{
base.CopyTo(c);
c.AllowDetach = AllowDetach;
c.AllowSelect = AllowSelect;
c.DetachedOffset = DetachedOffset;
c.InnerSliceLabel = InnerSliceLabel;
c.IsDetached = IsDetached;
c.IsInOther = IsInOther;
c.IsSelected = IsSelected;
c.Name = Name;
c.OuterSliceLabel = OuterSliceLabel;
if (_SeriesPoints != null)
{
PieSeriesPointCollection spc = SeriesPoints;
if (spc.Count > 0)
{
foreach (PieSeriesPoint psp in spc)
{
PieSeriesPoint pspCopy = psp.Copy();
c.SeriesPoints.Add(pspCopy);
}
}
}
c.SubSliceVisualLayout = (_SliceVisualLayout != null) ? _SliceVisualLayout.Copy() : null;
c.SliceVisualStyles = (_SliceVisualStyles != null) ? _SliceVisualStyles.Copy() : null;
c.StartAngle = StartAngle;
c.SweepAngle = SweepAngle;
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(bool root)
{
SerialElementCollection sec = new SerialElementCollection();
if (root == true)
sec.AddStartElement("SeriesPoint");
sec.AddValue("AllowDetach", AllowDetach, true);
sec.AddValue("AllowSelect", AllowSelect, true);
sec.AddValue("DetachedOffset", DetachedOffset, double.NaN);
sec.AddValue("InnerSliceLabel", InnerSliceLabel, null);
sec.AddValue("IsDetached", IsDetached, false);
sec.AddValue("IsInOther", IsInOther, false);
sec.AddValue("IsSelected", IsSelected, false);
sec.AddValue("Name", Name, null);
sec.AddValue("OuterSliceLabel", OuterSliceLabel, null);
sec.AddValue("StartAngle", StartAngle, double.NaN);
sec.AddValue("SweepAngle", SweepAngle, double.NaN);
if (_SeriesPoints != null)
{
PieSeriesPointCollection spc = SeriesPoints;
if (spc.Count > 0)
{
sec.AddStartElement("SeriesPoints count=\"" + spc.Count + "\"");
foreach (PieSeriesPoint psp in spc)
sec.AddElement(psp.GetSerialData());
sec.AddEndElement("SeriesPoints");
}
}
if (_SliceVisualLayout != null)
sec.AddElement(_SliceVisualLayout.GetSerialData());
if (_SliceVisualStyles != null && _SliceVisualStyles.IsEmpty == false)
sec.AddElement(_SliceVisualStyles.GetSerialData("SliceVisualStyles"));
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(false));
if (root == true)
sec.AddEndElement("SeriesPoint");
return (sec);
}
#endregion
#region PutSerialData
#region ProcessValue
internal override void ProcessValue(SerialElement se)
{
switch (se.Name)
{
case "AllowDetach":
AllowDetach = bool.Parse(se.StringValue);
break;
case "AllowSelect":
AllowSelect = bool.Parse(se.StringValue);
break;
case "DetachedOffset":
DetachedOffset = double.Parse(se.StringValue);
break;
case "InnerSliceLabel":
InnerSliceLabel = se.StringValue;
break;
case "IsDetached":
IsDetached = bool.Parse(se.StringValue);
break;
case "IsInOther":
IsInOther = bool.Parse(se.StringValue);
break;
case "IsSelected":
IsSelected = bool.Parse(se.StringValue);
break;
case "Name":
Name = se.StringValue;
break;
case "OuterSliceLabel":
OuterSliceLabel = se.StringValue;
break;
case "StartAngle":
StartAngle = double.Parse(se.StringValue);
break;
case "SweepAngle":
SweepAngle = double.Parse(se.StringValue);
break;
case "CheckedInLegend":
CheckedInLegend = bool.Parse(se.StringValue);
break;
case "LegendText":
LegendText = se.StringValue;
break;
case "ShowCheckBoxInLegend":
ShowCheckBoxInLegend = 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;
default:
base.ProcessValue(se);
break;
}
}
#endregion
#region ProcessCollection
internal override void ProcessCollection(SerialElement se)
{
SerialElementCollection sec = se.Sec;
switch (se.Name)
{
case "SeriesPoints":
if (se.ArrayCount > 0)
{
SeriesPoints = new PieSeriesPointCollection();
sec.PutSerialData(this);
}
break;
case "SeriesPoint":
PieSeriesPoint sp = new PieSeriesPoint();
sec.PutSerialData(sp);
SeriesPoints.Add(sp);
break;
case "SliceVisualLayout":
sec.PutSerialData(SubSliceVisualLayout);
break;
case "SliceVisualStyles":
se.Sec.PutSerialData(SliceVisualStyles);
break;
default:
base.ProcessCollection(se);
break;
}
}
#endregion
#endregion
#region INotifyPropertyChanged Members
/// <summary>
/// Occurs when property value has changed.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
#region OnPropertyChanged
/// <summary>
/// Raises the PropertyChanged event.
/// </summary>
/// <param name="e">Event arguments</param>
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
PropertyChanged(this, e);
VisualPropertyChangedEventArgs vce = e as VisualPropertyChangedEventArgs;
if (vce != null)
NotifyVisualParent(this, vce.ChangeType);
}
/// <summary>
/// Default PropertyChanged processing
/// </summary>
/// <param name="s"></param>
protected void OnPropertyChanged(string s)
{
if (PropertyChanged != null)
OnPropertyChanged(new PropertyChangedEventArgs(s));
}
/// <summary>
/// Default PropertyChanged processing
/// </summary>
/// <param name="s"></param>
/// <param name="changeType">invalidate</param>
protected void OnPropertyChangedEx(string s, VisualChangeType changeType)
{
if (PropertyChanged != null)
OnPropertyChanged(new VisualPropertyChangedEventArgs(s, changeType));
}
#endregion
#region NotifyVisualParent
internal void NotifyVisualParent(object sender, VisualChangeType vct)
{
ChartVisualElement cve = GetParentCve(sender);
if (cve != null)
{
if (vct == VisualChangeType.Recalc)
{
cve.InvalidateRecalc();
cve.InvalidateLayout();
}
else if (vct == VisualChangeType.Layout)
{
cve.InvalidateLayout();
}
else
{
PieSeriesPoint psp = (PieSeriesPoint)sender;
cve.InvalidateRender(psp.PathBounds);
if (psp.PieLabel != null)
{
if (psp.PieLabel.Bounds.IsEmpty == false)
{
cve.InvalidateRender(psp.PieLabel.Bounds);
if (psp.PieLabel.ConnectorBounds.IsEmpty == false)
cve.InvalidateRender(psp.PieLabel.ConnectorBounds);
}
}
}
}
}
#region GetParentCve
private ChartVisualElement GetParentCve(object sender)
{
object parent = sender;
while (parent != null)
{
if (parent is ChartVisualElement)
break;
if (parent is PieSeriesPoint)
parent = ((PieSeriesPoint)parent).Parent;
else if (parent is PieSeriesPointCollection)
parent = ((PieSeriesPointCollection)parent).Parent;
else
parent = null;
}
return ((ChartVisualElement)parent);
}
#endregion
#endregion
#endregion
#region InvalidateRender
public void InvalidateRender()
{
ChartVisualElement cve = GetParentCve(Parent);
if (cve != null)
{
cve.InvalidateRender(PathBounds);
if (PieLabel != null)
{
if (PieLabel.Bounds.IsEmpty == false)
{
cve.InvalidateRender(PieLabel.Bounds);
if (PieLabel.ConnectorBounds.IsEmpty == false)
cve.InvalidateRender(PieLabel.ConnectorBounds);
}
}
}
}
#endregion
#region IDispose
public override void Dispose()
{
SubSliceVisualLayout = null;
SliceVisualStyles = null;
base.Dispose();
}
#endregion
}
#endregion
[Editor("DevComponents.Charts.Design.SeriesPointCollectionEditor, DevComponents.Charts.Design, " +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public class SeriesPointCollection : CustomCollection<SeriesPoint>
{
}
#region SeriesPoint
[DesignTimeVisible(false), ToolboxItem(false)]
public class SeriesPoint : IProcessSerialElement, IDisposable
{
#region Private variables
private object _ValueX;
private object[] _ValueY;
private Point[] _Point;
private int _SeriesValidationCount;
private Size _PointSize;
private States _States;
private object _DataItem;
private object _Tag;
#endregion
#region Constructors
public SeriesPoint()
: this(0, 0)
{
}
public SeriesPoint(object xValue)
{
_Point = new Point[1];
ValueX = xValue;
InitDefaultStates();
}
public SeriesPoint(object xValue, object yValue)
{
_ValueY = new object[1];
_Point = new Point[1];
ValueX = xValue;
_ValueY[0] = yValue;
InitDefaultStates();
}
public SeriesPoint(object xValue, object yValue, object size)
{
_ValueY = new object[2];
_Point = new Point[1];
ValueX = xValue;
_ValueY[0] = yValue;
_ValueY[1] = size;
InitDefaultStates();
}
public SeriesPoint(object xValue, object yValue, object size, object intensity)
{
_ValueY = new object[3];
_Point = new Point[1];
ValueX = xValue;
_ValueY[0] = yValue;
_ValueY[1] = size;
_ValueY[2] = intensity;
InitDefaultStates();
}
public SeriesPoint(object xValue, object[] yValue)
{
_ValueY = new object[yValue.Length];
_Point = new Point[yValue.Length];
ValueX = xValue;
for (int i = 0; i < yValue.Length; i++)
{
_ValueY[i] = yValue[i];
if (i > 0)
{
if (IsQuantitativeYValue != IsQuantitativeValue(yValue[i]))
throw new ArgumentException("Cannot have mixed qualitative/quantitative yValues");
}
}
InitDefaultStates();
}
#endregion
#region InitDefaultStates
private void InitDefaultStates()
{
SetState(States.Visible, true);
}
#endregion
#region Public properties
#region DataItem
///<summary>
/// Gets the object to which the Point is bound.
///</summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public object DataItem
{
get { return (_DataItem); }
internal set { _DataItem = value; }
}
#endregion
#region IsEmpty
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool IsEmpty
{
get { return (IsEmptyPoint || IsEmptyValue); }
}
#endregion
#region IsEmptyPoint
/// <summary>
/// Gets or sets whether the point is an 'Empty' (or missing) Point.
/// </summary>
[DefaultValue(false)]
public virtual bool IsEmptyPoint
{
get { return (TestState(States.IsEmptyPoint)); }
set { SetState(States.IsEmptyPoint, value); }
}
#endregion
#region IsEmptyValue
/// <summary>
/// Gets whether the point is an 'Empty' value.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool IsEmptyValue
{
get { return (TestState(States.IsEmptyValue)); }
internal set { SetState(States.IsEmptyValue, value); }
}
#endregion
#region IsQualitativeXValue
/// <summary>
/// Gets whether the X Value is a Qualitative value.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool IsQualitativeXValue
{
get { return (TestState(States.IsQualitativeXValue)); }
internal set { SetState(States.IsQualitativeXValue, value); }
}
#endregion
#region IsQualitativeYValue
/// <summary>
/// Gets whether the Y Values are a Qualitative values.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool IsQualitativeYValue
{
get { return (IsQuantitativeYValue == false); }
}
#endregion
#region IsQuantitativeXValue
/// <summary>
/// Gets whether the X Value is a Quantitative value.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool IsQuantitativeXValue
{
get { return (!IsQualitativeXValue); }
internal set { IsQualitativeXValue = !value; }
}
#endregion
#region IsQuantitativeYValue
/// <summary>
/// Gets whether the Y Values are Quantitative values.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool IsQuantitativeYValue
{
get
{
if (_ValueY != null && _ValueY.Length > 0)
return (IsQuantitativeValue(_ValueY[0]));
return (true);
}
}
#endregion
#region Tag
///<summary>
/// Gets or sets user-defined data associated with the point
///</summary>
[DefaultValue(null)]
[Description("Indicates the user-defined data associated with the point.")]
[TypeConverter("DevComponents.Charts.Design.PointValueConverter, DevComponents.Charts.Design," +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf")]
public object Tag
{
get { return (_Tag); }
set { _Tag = value; }
}
#endregion
#region ValueX
/// <summary>
/// Gets or sets the X-Axis Value.
/// </summary>
[Category("Data")]
[Description("Indicates the X-Axis Value.")]
[TypeConverter("DevComponents.Charts.Design.PointValueConverter, DevComponents.Charts.Design," +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf")]
public object ValueX
{
get { return (_ValueX); }
set
{
_ValueX = value;
IsQuantitativeXValue = IsQuantitativeValue(value);
}
}
#endregion
#region ValueY
/// <summary>
/// Gets or sets the Y-Axis Values.
/// </summary>
[Category("Data")]
[Description("Indicates the Y-Axis Values.")]
[Editor("DevComponents.Charts.Design.SeriesPointValueEditor, DevComponents.Charts.Design, " +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public object[] ValueY
{
get { return (_ValueY); }
set { _ValueY = value; }
}
#endregion
#region Visible
/// <summary>
/// Gets or sets whether the point is Visible.
/// </summary>
[DefaultValue(true)]
public virtual bool Visible
{
get { return (TestState(States.Visible)); }
set { SetState(States.Visible, value); }
}
#endregion
#endregion
#region Internal properties
#region Point
internal Point[] Point
{
get { return (_Point); }
set { _Point = value; }
}
#endregion
#region PointSize
internal Size PointSize
{
get { return (_PointSize); }
set { _PointSize = value; }
}
#endregion
#region SeriesValidationCount
internal int SeriesValidationCount
{
get { return (_SeriesValidationCount); }
set { _SeriesValidationCount = value; }
}
#endregion
#endregion
#region InvalidatePoints
internal void InvalidatePoints()
{
if (_Point != null)
_Point = new Point[_Point.Length];
}
#endregion
#region IsQuantitativeValue
private bool IsQuantitativeValue(object value)
{
if (value is string || value is bool || value is char)
return (false);
return (true);
}
#endregion
#region IsQualitativeValue
private bool IsQualitativeValue(object value)
{
return (IsQuantitativeValue(value) == false);
}
#endregion
#region GetScaleType
public static ScaleType GetScaleType(Type dataType)
{
if (dataType == typeof(DateTime))
return (ScaleType.DateTime);
if (dataType == typeof(string) || dataType == typeof(bool) || dataType == typeof(char))
return (ScaleType.Qualitative);
return (ScaleType.Quantitative);
}
#endregion
#region Copy/CopyTo
/// <summary>
/// Creates a copy of the SeriesPoint
/// </summary>
/// <returns></returns>
public SeriesPoint Copy()
{
SeriesPoint copy = new SeriesPoint(ValueX);
CopyTo(copy);
return (copy);
}
/// <summary>
/// Copies the item data to the given SeriesPoint.
/// </summary>
/// <param name="sp"></param>
public void CopyTo(SeriesPoint sp)
{
sp.IsEmptyPoint = IsEmptyPoint;
sp.Tag = Tag;
sp.ValueX = ValueX;
if (ValueY != null)
{
sp.ValueY = new object[ValueY.Length];
sp.Point = new Point[ValueY.Length];
for (int i = 0; i < ValueY.Length; i++)
sp.ValueY[i] = ValueY[i];
}
}
#endregion
#region GetSerialData
internal virtual SerialElementCollection GetSerialData()
{
return (GetSerialData(true));
}
internal virtual SerialElementCollection GetSerialData(bool root)
{
SerialElementCollection sec = new SerialElementCollection();
if (root == true)
sec.AddStartElement("SeriesPoint");
sec.AddDataValue("Tag", Tag, null);
sec.AddDataValue("ValueX", ValueX);
if (ValueY != null)
{
if (ValueY.Length == 1)
{
sec.AddDataValue("ValueY0", ValueY[0]);
}
else
{
sec.AddStartElement("ValueYs count=\"" + ValueY.Length + "\"");
for (int i = 0; i < ValueY.Length; i++)
sec.AddDataValue("ValueY", ValueY[i]);
sec.AddEndElement("ValueYs");
}
}
if (root == true)
sec.AddEndElement("SeriesPoint");
return (sec);
}
#endregion
#region PutSerialData
#region ProcessValue
void IProcessSerialElement.ProcessValue(SerialElement se)
{
ProcessValue(se);
}
internal virtual void ProcessValue(SerialElement se)
{
switch (se.Name)
{
case "Tag":
Tag = se.DataValue;
break;
case "ValueX":
ValueX = se.DataValue;
break;
case "ValueY":
ValueY[se.ValueIndex] = se.DataValue;
break;
case "ValueY0":
ValueY = new object[1];
ValueY[0] = se.DataValue;
break;
default:
throw new Exception("Unknown Serial Value (" + se.Name + ")");
}
}
#endregion
#region ProcessCollection
void IProcessSerialElement.ProcessCollection(SerialElement se)
{
ProcessCollection(se);
}
internal virtual void ProcessCollection(SerialElement se)
{
switch (se.Name)
{
case "ValueYs":
if (se.ArrayCount > 0)
{
ValueY = new object[se.ArrayCount];
se.Sec.PutSerialData(this);
}
break;
default:
throw new Exception("Unknown Serial Collection (" + se.Name + ")");
}
}
#endregion
#endregion
#region States
[Flags]
private enum States : uint
{
IsQualitativeXValue = (1U << 0),
IsQualitativeYValue = (1U << 1),
IsEmptyPoint = (1U << 2),
IsEmptyValue = (1U << 3),
Visible = (1U << 4),
}
#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 ToString
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append("SeriesPoint (");
sb.Append(FormatToStringValue(ValueX));
sb.Append(",");
if (ValueY != null && ValueY.Length > 0)
{
if (ValueY.Length > 1)
sb.Append("[");
foreach (object value in ValueY)
{
sb.Append(FormatToStringValue(value));
sb.Append(",");
}
sb.Length--;
if (ValueY.Length > 1)
sb.Append("]");
}
sb.Append(")");
return (sb.ToString());
}
#region FormatToStringValue
private string FormatToStringValue(object value)
{
if (value == null)
return ("<null>");
if (value is string)
return ("\"" + value + "\"");
if (value is int)
return (value.ToString());
if (value is DateTime)
return (value.ToString());
return (String.Format("{0:0.0###############}", value));
}
#endregion
#endregion
#region IDispose
public virtual void Dispose()
{
}
#endregion
}
#region PointValueConvertor
///<summary>
/// PointValueConvertor
///</summary>
public class PointValueConvertor : BlankExpandableObjectConverter
{
public override object ConvertTo(
ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
{
if (value == null)
return ("<null>");
if (value is string)
return ("\"" + value + "\"");
if (value is int)
return (value.ToString());
if (value is DateTime)
return (value.ToString());
return (String.Format("{0:0.0}", value));
}
return (base.ConvertTo(context, culture, value, destinationType));
}
}
#endregion
#endregion
}