DotNet 4.8.1 build of DotNetBar
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,280 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using DevComponents.DotNetBar.Charts.Style;
|
||||
|
||||
namespace DevComponents.DotNetBar.Charts
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a PieLabel (label associated with a pie data slice in the chart).
|
||||
/// </summary>
|
||||
public class PieLabel : IDisposable
|
||||
{
|
||||
#region Private data
|
||||
|
||||
private PieSeriesPoint _PieSeriesPoint;
|
||||
|
||||
private float _Angle;
|
||||
private Rectangle _Bounds;
|
||||
private Rectangle _ConnectorBounds;
|
||||
|
||||
private Point _PtBoxEdge;
|
||||
private Point _PtBoxBend;
|
||||
private Point _PtSliceEdge;
|
||||
|
||||
private double _Radius;
|
||||
private double _OuterRadius;
|
||||
|
||||
private string _Label;
|
||||
private Size _LabelSize;
|
||||
|
||||
private SliceOuterLabelVisualStyle _SliceLabelVisualStyle;
|
||||
|
||||
private States _States;
|
||||
|
||||
#endregion
|
||||
|
||||
public PieLabel(PieSeriesPoint sp, string label)
|
||||
{
|
||||
_PieSeriesPoint = sp;
|
||||
_Label = label;
|
||||
|
||||
InitDefaultStates();
|
||||
}
|
||||
|
||||
#region InitDefaultStates
|
||||
|
||||
private void InitDefaultStates()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public properties
|
||||
|
||||
#region Angle
|
||||
|
||||
/// <summary>
|
||||
/// Gets the angle used to display the point label
|
||||
/// associated with the data point.
|
||||
/// </summary>
|
||||
public float Angle
|
||||
{
|
||||
get { return (_Angle); }
|
||||
internal set { _Angle = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Bounds
|
||||
|
||||
/// <summary>
|
||||
/// Gets the label text bounds.
|
||||
/// </summary>
|
||||
public Rectangle Bounds
|
||||
{
|
||||
get { return (_Bounds); }
|
||||
internal set { _Bounds = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsLeftlabel
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the label is a left positioned
|
||||
/// label (with respect to the chart slice).
|
||||
/// </summary>
|
||||
public bool IsLeftlabel
|
||||
{
|
||||
get { return (!TestState(States.RightLabel)); }
|
||||
internal set { SetState(States.RightLabel, !value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsRightlabel
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the label is a right positioned
|
||||
/// label (with respect to the chart slice).
|
||||
/// </summary>
|
||||
public bool IsRightlabel
|
||||
{
|
||||
get { return (TestState(States.RightLabel)); }
|
||||
internal set { SetState(States.RightLabel, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Label
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the label text
|
||||
/// </summary>
|
||||
public string Label
|
||||
{
|
||||
get { return (_Label); }
|
||||
internal set { _Label = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region LabelSize
|
||||
|
||||
/// <summary>
|
||||
/// Gets the label size.
|
||||
/// </summary>
|
||||
public Size LabelSize
|
||||
{
|
||||
get { return (_LabelSize); }
|
||||
internal set { _LabelSize = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PieSeriesPoint
|
||||
|
||||
/// <summary>
|
||||
/// Gets the associated PieSeriesPoint.
|
||||
/// </summary>
|
||||
public PieSeriesPoint PieSeriesPoint
|
||||
{
|
||||
get { return (_PieSeriesPoint); }
|
||||
internal set { _PieSeriesPoint = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PtBoxBend
|
||||
|
||||
/// <summary>
|
||||
/// Gets the middle connector point located
|
||||
/// at the 'bend' of the connector.
|
||||
/// </summary>
|
||||
public Point PtBoxBend
|
||||
{
|
||||
get { return (_PtBoxBend); }
|
||||
internal set { _PtBoxBend = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PtBoxEdge
|
||||
|
||||
/// <summary>
|
||||
/// Gets the connector point located and the
|
||||
/// 'edge' of the label text bounding box.
|
||||
/// </summary>
|
||||
public Point PtBoxEdge
|
||||
{
|
||||
get { return (_PtBoxEdge); }
|
||||
internal set { _PtBoxEdge = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PtSliceEdge
|
||||
|
||||
/// <summary>
|
||||
/// Gets the initial connector point, located at
|
||||
/// the edge of the pie slice.
|
||||
/// </summary>
|
||||
public Point PtSliceEdge
|
||||
{
|
||||
get { return (_PtSliceEdge); }
|
||||
internal set { _PtSliceEdge = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SliceLabelVisualStyle
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current slice label VisualStyle for the label.
|
||||
/// </summary>
|
||||
public SliceOuterLabelVisualStyle LabelStyle
|
||||
{
|
||||
get { return (_SliceLabelVisualStyle); }
|
||||
internal set { _SliceLabelVisualStyle = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal properties
|
||||
|
||||
#region ConnectorBounds
|
||||
|
||||
internal Rectangle ConnectorBounds
|
||||
{
|
||||
get { return (_ConnectorBounds); }
|
||||
set { _ConnectorBounds = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region OuterRadius
|
||||
|
||||
internal double OuterRadius
|
||||
{
|
||||
get { return (_OuterRadius); }
|
||||
set { _OuterRadius = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Radius
|
||||
|
||||
internal double Radius
|
||||
{
|
||||
get { return (_Radius); }
|
||||
set { _Radius = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region States
|
||||
|
||||
[Flags]
|
||||
private enum States : uint
|
||||
{
|
||||
RightLabel = (1U << 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 IDisposable
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,404 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Design;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Windows.Forms;
|
||||
using DevComponents.Charts.TextMarkup;
|
||||
using DevComponents.DotNetBar.Charts.Style;
|
||||
|
||||
namespace DevComponents.DotNetBar.Charts
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the collection of PieReferenceLines.
|
||||
/// </summary>
|
||||
[Editor("DevComponents.Charts.Design.PieReferenceCollectionEditor, DevComponents.Charts.Design, " +
|
||||
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
|
||||
public class PieReferenceLineCollection : CustomNamedCollection<PieReferenceLine>
|
||||
{
|
||||
#region GetUniqueName
|
||||
|
||||
/// <summary>
|
||||
/// Gets a unique (unused) reference line Name.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string GetUniqueName()
|
||||
{
|
||||
return (GetUniqueName("PieRefLine"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a reference line (a radial line on the chart
|
||||
/// that can be used to signify, or reference, a specific chart value).
|
||||
/// </summary>
|
||||
public class PieReferenceLine : ChartVisualElement
|
||||
{
|
||||
#region Private variables
|
||||
|
||||
private double _Value;
|
||||
|
||||
private PieReferenceLineVisualStyle _ReferenceLineVisualStyle;
|
||||
private EffectiveStyle<PieReferenceLineVisualStyle> _EffectiveStyle;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// PieReferenceLine
|
||||
/// </summary>
|
||||
public PieReferenceLine()
|
||||
{
|
||||
_EffectiveStyle = new EffectiveStyle<PieReferenceLineVisualStyle>(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// PieReferenceLine
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
public PieReferenceLine(string name)
|
||||
: this()
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// PieReferenceLine
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="radialValue"></param>
|
||||
public PieReferenceLine(string name, double value)
|
||||
: this(name)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public properties
|
||||
|
||||
#region EffectiveStyle
|
||||
|
||||
/// <summary>
|
||||
/// Gets a reference to the ReferenceLine's Effective (cached, composite) style.
|
||||
/// </summary>
|
||||
[Browsable(false)]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public PieReferenceLineVisualStyle EffectiveStyle
|
||||
{
|
||||
get { return (_EffectiveStyle.Style); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ReferenceLineVisualStyle
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the visual style for the Reference Line.
|
||||
/// </summary>
|
||||
[Category("Style")]
|
||||
[Description("Indicates the visual style for the ReferenceLine.")]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
||||
public PieReferenceLineVisualStyle ReferenceLineVisualStyle
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_ReferenceLineVisualStyle == null)
|
||||
{
|
||||
_ReferenceLineVisualStyle = new PieReferenceLineVisualStyle();
|
||||
|
||||
StyleVisualChangeHandler(null, _ReferenceLineVisualStyle);
|
||||
}
|
||||
|
||||
return (_ReferenceLineVisualStyle);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (_ReferenceLineVisualStyle != value)
|
||||
{
|
||||
PieReferenceLineVisualStyle oldValue = _ReferenceLineVisualStyle;
|
||||
|
||||
_ReferenceLineVisualStyle = value;
|
||||
|
||||
OnVisualStyleChanged("ReferenceLineVisualStyle", oldValue, value);
|
||||
|
||||
if (oldValue != null)
|
||||
oldValue.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Value
|
||||
|
||||
///<summary>
|
||||
/// Gets or sets the associated radial grid value of the reference line.
|
||||
///</summary>
|
||||
[DefaultValue(null), Category("Appearance")]
|
||||
[Description("Indicates the associated radial grid value of the reference line.")]
|
||||
//[TypeConverter("DevComponents.Charts.Design.PointValueConverter," +
|
||||
// "DevComponents.Charts.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf")]
|
||||
public double Value
|
||||
{
|
||||
get { return (_Value); }
|
||||
|
||||
set
|
||||
{
|
||||
if (value != _Value)
|
||||
{
|
||||
_Value = value;
|
||||
|
||||
OnPropertyChangedEx("Value", VisualChangeType.Render);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal properties
|
||||
|
||||
#endregion
|
||||
|
||||
#region MeasureOverride
|
||||
|
||||
protected override void MeasureOverride(ChartLayoutInfo layoutInfo)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ArrangeOverride
|
||||
|
||||
protected override void ArrangeOverride(ChartLayoutInfo layoutInfo)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region RenderOverride
|
||||
|
||||
protected override void RenderOverride(ChartRenderInfo renderInfo)
|
||||
{
|
||||
}
|
||||
|
||||
#region RenderLine
|
||||
|
||||
internal void RenderLine(ChartRenderInfo renderInfo)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region InvalidateRender
|
||||
|
||||
public override void InvalidateRender()
|
||||
{
|
||||
ChartVisualElement cve = Parent as ChartVisualElement;
|
||||
|
||||
if (cve != null)
|
||||
cve.InvalidateRender();
|
||||
else
|
||||
base.InvalidateRender();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Style handling
|
||||
|
||||
#region ApplyStyles
|
||||
|
||||
public override void ApplyStyles(BaseVisualStyle style)
|
||||
{
|
||||
ChartLineVisualStyle rstyle = style as ChartLineVisualStyle;
|
||||
|
||||
if (rstyle != null)
|
||||
{
|
||||
ApplyParentStyles(rstyle, Parent as ChartContainer);
|
||||
|
||||
rstyle.ApplyStyle(ReferenceLineVisualStyle);
|
||||
|
||||
if (rstyle.LineColor.IsEmpty == true)
|
||||
rstyle.LineColor = Color.Red;
|
||||
|
||||
if (rstyle.LineWidth < 0)
|
||||
rstyle.LineWidth = 1;
|
||||
}
|
||||
}
|
||||
|
||||
#region ApplyParentStyles
|
||||
|
||||
private void ApplyParentStyles(ChartLineVisualStyle pstyle, ChartContainer item)
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
ApplyParentStyles(pstyle, item.Parent as ChartContainer);
|
||||
|
||||
ChartPanel chartPanel = item as ChartPanel;
|
||||
|
||||
if (chartPanel != null)
|
||||
{
|
||||
pstyle.ApplyStyle(chartPanel.DefaultVisualStyles.PieChartVisualStyle.ReferenceLineVisualStyle);
|
||||
}
|
||||
else if (item is PieChart)
|
||||
{
|
||||
PieChart pieChart = (PieChart)item;
|
||||
|
||||
pstyle.ApplyStyle(pieChart.ChartVisualStyle.ReferenceLineVisualStyle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pstyle.ApplyStyle(ChartControl.BaseVisualStyles.ReferenceLineVisualStyle);
|
||||
pstyle.ApplyStyle(ChartControl.DefaultVisualStyles.ReferenceLineVisualStyle);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region InvalidateStyle
|
||||
|
||||
///<summary>
|
||||
///Invalidate the cached Style definition
|
||||
///</summary>
|
||||
public void InvalidateStyle()
|
||||
{
|
||||
ClearEffectiveStyles();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ClearEffectiveStyles
|
||||
|
||||
protected override void ClearEffectiveStyles()
|
||||
{
|
||||
if (_EffectiveStyle.InvalidateStyle() == true)
|
||||
InvalidateLayout();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Copy/CopyTo
|
||||
|
||||
public override ChartVisualElement Copy()
|
||||
{
|
||||
PieReferenceLine copy = new PieReferenceLine();
|
||||
|
||||
CopyTo(copy);
|
||||
|
||||
return (copy);
|
||||
}
|
||||
|
||||
public override void CopyTo(ChartVisualElement copy)
|
||||
{
|
||||
PieReferenceLine c = copy as PieReferenceLine;
|
||||
|
||||
if (c != null)
|
||||
{
|
||||
base.CopyTo(c);
|
||||
|
||||
c.Value = Value;
|
||||
|
||||
c.ReferenceLineVisualStyle =
|
||||
(_ReferenceLineVisualStyle != null) ? ReferenceLineVisualStyle.Copy() : null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetSerialData
|
||||
|
||||
internal override SerialElementCollection GetSerialData(string serialName)
|
||||
{
|
||||
SerialElementCollection sec = new SerialElementCollection();
|
||||
|
||||
if (serialName != null)
|
||||
{
|
||||
if (serialName.Equals("") == true)
|
||||
serialName = "PieReferenceLine";
|
||||
|
||||
sec.AddStartElement(serialName);
|
||||
}
|
||||
|
||||
if (_ReferenceLineVisualStyle != null && _ReferenceLineVisualStyle.IsEmpty == false)
|
||||
sec.AddElement(_ReferenceLineVisualStyle.GetSerialData("ReferenceLineVisualStyle"));
|
||||
|
||||
sec.AddValue("Value", Value, null);
|
||||
|
||||
sec.AddElement(base.GetSerialData(null));
|
||||
|
||||
if (serialName != null)
|
||||
sec.AddEndElement(serialName);
|
||||
|
||||
return (sec);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PutSerialData
|
||||
|
||||
#region ProcessValue
|
||||
|
||||
internal override void ProcessValue(SerialElement se)
|
||||
{
|
||||
switch (se.Name)
|
||||
{
|
||||
case "Value":
|
||||
Value = double.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 "ReferenceLineVisualStyle":
|
||||
sec.PutSerialData(ReferenceLineVisualStyle);
|
||||
break;
|
||||
|
||||
default:
|
||||
base.ProcessCollection(se);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
ReferenceLineVisualStyle = null;
|
||||
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,918 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Windows.Forms;
|
||||
using DevComponents.DotNetBar.Charts.Style;
|
||||
|
||||
namespace DevComponents.DotNetBar.Charts
|
||||
{
|
||||
public class PieRing : ILegendItem, ILegendItemEx, INotifyPropertyChanged
|
||||
{
|
||||
#region Private variables
|
||||
|
||||
private int _RingLevel;
|
||||
private int _RingWeight = -1;
|
||||
|
||||
private int _InnerRadius;
|
||||
private int _OuterRadius;
|
||||
private int _ExtentRadius;
|
||||
|
||||
private PieSeries _ChartSeries;
|
||||
private List<PieSeriesPoint> _Psps;
|
||||
|
||||
private ChartLegendItem _LegendItem;
|
||||
private string _LegendText;
|
||||
private ChartLegendItemVisualStyles _ChartLegendItemVisualStyles;
|
||||
|
||||
private string _Name;
|
||||
|
||||
private States _States;
|
||||
|
||||
#endregion
|
||||
|
||||
public PieRing()
|
||||
{
|
||||
InitDefaultStates();
|
||||
}
|
||||
|
||||
public PieRing(int ringLevel)
|
||||
: this()
|
||||
{
|
||||
RingLevel = ringLevel;
|
||||
}
|
||||
|
||||
#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);
|
||||
|
||||
SetState(States.Visible, true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public properties
|
||||
|
||||
#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 ring can be selected by clicking on it. Defaults to true.
|
||||
/// </summary>
|
||||
[DefaultValue(true), Category("Behavior")]
|
||||
[Description("Indicates whether the ring 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("AllowSelect");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsDisplayed
|
||||
|
||||
///<summary>
|
||||
/// Gets whether the ring is displayed (based upon Visibility and Legend state).
|
||||
///</summary>
|
||||
[Browsable(false)]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public bool IsDisplayed
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ChartSeries != null)
|
||||
{
|
||||
PieChart pieChart = ChartSeries.Parent as PieChart;
|
||||
|
||||
if (pieChart != null)
|
||||
{
|
||||
ItemCheckAction ica = (pieChart != null)
|
||||
? pieChart.Legend.ItemCheckAction : ItemCheckAction.ShowItem;
|
||||
|
||||
return ((Visible == true) &&
|
||||
(ica == ItemCheckAction.None ||
|
||||
(ShowCheckBoxInLegend == false || CheckedInLegend == true)));
|
||||
}
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Name
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the user assigned Name of the item.
|
||||
/// </summary>
|
||||
[DefaultValue("")]
|
||||
[Description("Indicates the Name of the item.")]
|
||||
public virtual string Name
|
||||
{
|
||||
get { return (_Name); }
|
||||
set { _Name = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region RingWeight
|
||||
|
||||
///<summary>
|
||||
/// Gets or sets the 'relative' thickness of the series ring, as
|
||||
/// compared to the relative thickness of other series
|
||||
/// rings.
|
||||
///</summary>
|
||||
[DefaultValue(-1), Category("Display")]
|
||||
[Description("Indicates the 'relative' thickness of the series ring, as compared to the relative thickness of other series rings.")]
|
||||
public int RingWeight
|
||||
{
|
||||
get { return (_RingWeight); }
|
||||
|
||||
set
|
||||
{
|
||||
if (value != _RingWeight)
|
||||
{
|
||||
_RingWeight = value;
|
||||
|
||||
OnPropertyChangedEx("RingWeight", Style.VisualChangeType.Recalc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Visible
|
||||
|
||||
/// <summary>
|
||||
/// Get or sets whether the item is visible
|
||||
/// </summary>
|
||||
[DefaultValue(true), Category("Appearance")]
|
||||
[Description("Indicates whether the item is visible")]
|
||||
public virtual bool Visible
|
||||
{
|
||||
get { return (TestState(States.Visible)); }
|
||||
|
||||
set
|
||||
{
|
||||
if (Visible != value)
|
||||
{
|
||||
SetState(States.Visible, value);
|
||||
|
||||
OnPropertyChangedEx("Visible", VisualChangeType.Layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal properties
|
||||
|
||||
#region ChartSeries
|
||||
|
||||
internal PieSeries ChartSeries
|
||||
{
|
||||
get { return (_ChartSeries); }
|
||||
set { _ChartSeries = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ExtentRadius
|
||||
|
||||
internal int ExtentRadius
|
||||
{
|
||||
get { return (_ExtentRadius); }
|
||||
set { _ExtentRadius = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region InnerRadius
|
||||
|
||||
internal int InnerRadius
|
||||
{
|
||||
get { return (_InnerRadius); }
|
||||
set { _InnerRadius = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsEnabled
|
||||
|
||||
internal bool IsEnabled
|
||||
{
|
||||
get { return (IsRingEnabled()); }
|
||||
}
|
||||
|
||||
#region IsRingEnabled
|
||||
|
||||
private bool IsRingEnabled()
|
||||
{
|
||||
if (ChartSeries != null)
|
||||
{
|
||||
int index = ChartSeries.PieRings.IndexOf(this);
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
for (int i = index - 1; i >= 0; i--)
|
||||
{
|
||||
PieRing pieRing = ChartSeries.PieRings[i];
|
||||
|
||||
if (pieRing.IsDisplayed == false)
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
return (ChartSeries.IsDisplayed);
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsInitialRing
|
||||
|
||||
internal bool IsInnerRing
|
||||
{
|
||||
get { return (TestState(States.InnerRing)); }
|
||||
set { SetState(States.InnerRing, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsOuterRing
|
||||
|
||||
internal bool IsOuterRing
|
||||
{
|
||||
get { return (TestState(States.OuterRing)); }
|
||||
set { SetState(States.OuterRing, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region OuterRadius
|
||||
|
||||
internal int OuterRadius
|
||||
{
|
||||
get { return (_OuterRadius); }
|
||||
set { _OuterRadius = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Psps
|
||||
|
||||
internal List<PieSeriesPoint> Psps
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_Psps == null)
|
||||
_Psps = new List<PieSeriesPoint>();
|
||||
|
||||
return (_Psps);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region RingLevel
|
||||
|
||||
internal int RingLevel
|
||||
{
|
||||
get { return (_RingLevel); }
|
||||
set { _RingLevel = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetSelectionCount
|
||||
|
||||
/// <summary>
|
||||
/// Gets a count of the visible selected pie series points.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int GetSelectionCount()
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
foreach (PieSeriesPoint psp in Psps)
|
||||
{
|
||||
if (psp.Visible == true)
|
||||
{
|
||||
if (psp.IsSelected == true)
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return (count);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region InvalidateRender
|
||||
|
||||
internal void InvalidateRender(PieChart pieChart)
|
||||
{
|
||||
foreach (PieSeriesPoint psp in Psps)
|
||||
pieChart.InvalidateRender(psp.PathBounds);
|
||||
}
|
||||
|
||||
#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);
|
||||
|
||||
ChartSeries.InvalidateLayout();
|
||||
|
||||
if (LegendItem != null)
|
||||
LegendItem.UpdateCheckState();
|
||||
|
||||
foreach (PieSeriesPoint psp in Psps)
|
||||
{
|
||||
if (psp.LegendItem != null)
|
||||
psp.LegendItem.IsEnabled = psp.IsEnabled;
|
||||
}
|
||||
|
||||
OnPropertyChangedEx("CheckedInLegend", VisualChangeType.Render);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#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 { 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()
|
||||
{
|
||||
_LegendItem = null;
|
||||
|
||||
if (ShowInLegend == true)
|
||||
{
|
||||
_LegendItem = new ChartLegendItem();
|
||||
|
||||
if (CheckedInLegend == true)
|
||||
_LegendItem.CheckState = CheckState.Checked;
|
||||
|
||||
_LegendItem.Name = Name;
|
||||
_LegendItem.ItemText = LegendText;
|
||||
|
||||
if (string.IsNullOrEmpty(_LegendItem.Name) == true)
|
||||
_LegendItem.Name = "(PieRing " + (RingLevel + 1) + ")";
|
||||
|
||||
_LegendItem.IsEnabled = IsEnabled;
|
||||
|
||||
_LegendItem.ChartItems.Add(this);
|
||||
}
|
||||
|
||||
return (_LegendItem);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetLegendItems
|
||||
|
||||
/// <summary>
|
||||
/// Creates a list of legend items associated with
|
||||
/// the item.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<ChartLegendItem> GetLegendItems()
|
||||
{
|
||||
List<ChartLegendItem> list = new List<ChartLegendItem>();
|
||||
|
||||
for (int i = 0; i < Psps.Count; i++)
|
||||
{
|
||||
PieSeriesPoint psp = Psps[i];
|
||||
|
||||
if (psp.IsDisplayable == true)
|
||||
{
|
||||
List<ChartLegendItem> items = psp.GetLegendItems();
|
||||
|
||||
if (items != null && items.Count > 0)
|
||||
list.AddRange(items);
|
||||
}
|
||||
}
|
||||
|
||||
return (list);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetLegendItemColor
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default color associated with the legend item.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Color GetLegendItemColor()
|
||||
{
|
||||
if (Psps.Count > 0)
|
||||
return (Psps[0].GetLegendItemColor());
|
||||
|
||||
return (ChartSeries.GetLegendItemColor());
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
Rectangle bounds = litem.MarkerBounds;
|
||||
bounds.Inflate(-1, -1);
|
||||
|
||||
bounds.Width--;
|
||||
bounds.Height--;
|
||||
|
||||
SmoothingMode sm = g.SmoothingMode;
|
||||
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
|
||||
if (IsEnabled == true)
|
||||
{
|
||||
Color color = GetLegendItemColor();
|
||||
|
||||
using (Pen pen = new Pen(color, 2))
|
||||
g.DrawEllipse(pen, bounds);
|
||||
}
|
||||
else
|
||||
{
|
||||
Color color = style.DisabledMarkerBackground.Color1;
|
||||
|
||||
if (color.IsEmpty == true)
|
||||
color = style.DisabledTextColor;
|
||||
|
||||
if (color.IsEmpty == true)
|
||||
color = Color.LightGray;
|
||||
|
||||
using (Pen pen = new Pen(color, 2))
|
||||
g.DrawEllipse(pen, bounds);
|
||||
}
|
||||
|
||||
g.SmoothingMode = sm;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region States
|
||||
|
||||
[Flags]
|
||||
private enum States : uint
|
||||
{
|
||||
AllowSelect = (1U << 0),
|
||||
AllowDetach = (1U << 1),
|
||||
|
||||
InnerRing = (1U << 2),
|
||||
OuterRing = (1U << 3),
|
||||
|
||||
CheckedInLegend = (1U << 4),
|
||||
ShowInLegend = (1U << 5),
|
||||
ShowInParentLegend = (1U << 6),
|
||||
ShowCheckBoxInLegend = (1U << 7),
|
||||
ShowMarkerInLegend = (1U << 8),
|
||||
|
||||
Visible = (1U << 9),
|
||||
}
|
||||
|
||||
#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 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
|
||||
|
||||
#region NotifyVisualParent
|
||||
|
||||
internal void NotifyVisualParent(object sender, VisualChangeType vct)
|
||||
{
|
||||
object parent = sender;
|
||||
|
||||
PieSeries series = ChartSeries;
|
||||
|
||||
if (series != null)
|
||||
{
|
||||
if (vct == VisualChangeType.Layout)
|
||||
series.InvalidateLayout();
|
||||
else
|
||||
series.InvalidateRender();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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
|
||||
|
||||
#region InvalidateRender
|
||||
|
||||
public void InvalidateRender()
|
||||
{
|
||||
PieSeries series = ChartSeries;
|
||||
|
||||
if (series != null)
|
||||
series.InvalidateRender();
|
||||
}
|
||||
|
||||
#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 (text);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,614 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using DevComponents.DotNetBar.Charts.Style;
|
||||
|
||||
namespace DevComponents.DotNetBar.Charts
|
||||
{
|
||||
class RadialAlign
|
||||
{
|
||||
#region Private variables
|
||||
|
||||
private List<PieLabel> _PieLabels;
|
||||
|
||||
#endregion
|
||||
|
||||
public RadialAlign(List<PieLabel> pieLabels)
|
||||
{
|
||||
_PieLabels = pieLabels;
|
||||
|
||||
foreach (PieLabel pl in _PieLabels)
|
||||
pl.Bounds = Rectangle.Empty;
|
||||
}
|
||||
|
||||
#region Iterate
|
||||
|
||||
public bool Iterate(Graphics g, PieChart pieChart, Rectangle bounds)
|
||||
{
|
||||
if (_PieLabels.Count > 0)
|
||||
{
|
||||
PositionLabels(pieChart, bounds);
|
||||
|
||||
List<PieLabel>[] plist = SortLabels();
|
||||
|
||||
for (int i = 0; i < plist.Length; i++)
|
||||
{
|
||||
List<PieLabel> pls = plist[i];
|
||||
|
||||
if (pls.Count > 0)
|
||||
{
|
||||
if (IsAnyOverlap(pieChart, pls) == true)
|
||||
{
|
||||
AdjustDownwards(pieChart, pls, bounds);
|
||||
|
||||
if (IsAnyOverlap(pieChart, pls) == true)
|
||||
AdjustUpwards(pieChart, pls, bounds);
|
||||
}
|
||||
|
||||
AdjustLabelSizes(g, pieChart, pls, bounds);
|
||||
|
||||
if (IsAnyOverlap(pieChart, pls) == true)
|
||||
{
|
||||
AdjustDownwards(pieChart, pls, bounds);
|
||||
|
||||
if (IsAnyOverlap(pieChart, pls) == true)
|
||||
AdjustUpwards(pieChart, pls, bounds);
|
||||
}
|
||||
|
||||
if (pieChart.SliceLabelOverlapMode != SliceLabelOverlapMode.ShowOverlapping)
|
||||
{
|
||||
if (IsAnyOverlap(pieChart, pls) == true)
|
||||
HideOverLapping(pls, bounds);
|
||||
}
|
||||
|
||||
UpdateBoxPoints(pieChart, pls);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
#region PositionLabels
|
||||
|
||||
private void PositionLabels(PieChart pieChart, Rectangle bounds)
|
||||
{
|
||||
foreach (PieLabel pl in _PieLabels)
|
||||
{
|
||||
PieSeriesPoint psp = pl.PieSeriesPoint;
|
||||
PieSeriesPointCollection spc = psp.Parent as PieSeriesPointCollection;
|
||||
|
||||
if (spc != null)
|
||||
{
|
||||
bool showWhiteSpace = psp.ShowSliceWhiteSpaceEx;
|
||||
|
||||
int width = psp.OuterRadius - psp.InnerRadius;
|
||||
|
||||
int outerRadius = (psp.ShowSliceWhiteSpaceEx == true)
|
||||
? psp.OuterRadius : (int)(psp.InnerRadius + psp.SliceExtent * width);
|
||||
|
||||
pl.LabelStyle = psp.GetEffectiveSliceStyle(pieChart, psp.ChartSeries).SliceOuterLabelStyle;
|
||||
|
||||
pl.OuterRadius = outerRadius;
|
||||
pl.Radius = outerRadius + pl.LabelStyle.ConnectorLength;
|
||||
|
||||
UpdateBoundingRect(pieChart, psp, pl, psp.CenterAngle);
|
||||
}
|
||||
}
|
||||
|
||||
AdjustForChartBounds(pieChart, _PieLabels);
|
||||
}
|
||||
|
||||
#region UpdateBoundingRect
|
||||
|
||||
private void UpdateBoundingRect(PieChart pieChart, PieSeriesPoint psp, PieLabel pl, double angle)
|
||||
{
|
||||
pl.PtSliceEdge = psp.GetRayEndPoint(angle, pl.OuterRadius);
|
||||
|
||||
Point pt = psp.GetRayEndPoint(angle, pl.Radius);
|
||||
|
||||
Rectangle r = new Rectangle(pt, pl.LabelSize);
|
||||
r.Y -= (r.Size.Height / 2);
|
||||
|
||||
angle = (angle + 360000) % 360;
|
||||
|
||||
int n = (pl.LabelStyle.DrawConnector == Tbool.True)
|
||||
? Dpi.Width(pl.LabelStyle.ConnectorTickLength) : 0;
|
||||
|
||||
r.X += ((angle >= 270 || angle <= 90) ? n : -(r.Size.Width + n));
|
||||
|
||||
pl.Bounds = r;
|
||||
|
||||
AdjustForPieIntersect(pl);
|
||||
}
|
||||
|
||||
#region AdjustForPieIntersect
|
||||
|
||||
private void AdjustForPieIntersect(PieLabel pl)
|
||||
{
|
||||
PieSeriesPoint psp = pl.PieSeriesPoint;
|
||||
|
||||
Point pto = GetClosestOffset(psp.SliceCenter, pl.Bounds);
|
||||
|
||||
Point ptr = psp.SliceCenter;
|
||||
ptr.X += pto.X;
|
||||
ptr.Y += pto.Y;
|
||||
|
||||
if (Intersects(psp, ptr, pl) == true)
|
||||
{
|
||||
Rectangle r = pl.Bounds;
|
||||
|
||||
double ihyp = Math.Sqrt(pto.X * pto.X + pto.Y * pto.Y);
|
||||
double ohyp = (psp.OuterRadius + pl.LabelStyle.LabelMargin) - ihyp;
|
||||
|
||||
double scale = ohyp / ihyp;
|
||||
|
||||
int dx = (int)(pto.X * scale);
|
||||
int dy = (int)(pto.Y * scale);
|
||||
|
||||
r.X += dx;
|
||||
r.Y += dy;
|
||||
|
||||
pl.Bounds = r;
|
||||
}
|
||||
}
|
||||
|
||||
#region GetClosestOffset
|
||||
|
||||
private Point GetClosestOffset(Point ptc, Rectangle r)
|
||||
{
|
||||
Point pt = new Point();
|
||||
|
||||
int dx1 = r.X - ptc.X;
|
||||
int dx2 = r.Right - ptc.X;
|
||||
|
||||
int dy1 = r.Y - ptc.Y;
|
||||
int dy2 = r.Bottom - ptc.Y;
|
||||
|
||||
pt.X = Math.Abs(dx1) < Math.Abs(dx2) ? dx1 : dx2;
|
||||
pt.Y = Math.Abs(dy1) < Math.Abs(dy2) ? dy1 : dy2;
|
||||
|
||||
return (pt);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Intersects
|
||||
|
||||
private bool Intersects(
|
||||
PieSeriesPoint psp, Point ptr, PieLabel pl)
|
||||
{
|
||||
int radius = psp.OuterRadius + pl.LabelStyle.LabelMargin;
|
||||
|
||||
int dx = psp.SliceCenter.X - ptr.X;
|
||||
int dy = psp.SliceCenter.Y - ptr.Y;
|
||||
|
||||
float dsq = (dx * dx) + (dy * dy);
|
||||
|
||||
return (dsq < (radius * radius));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region AdjustForChartBounds
|
||||
|
||||
private void AdjustForChartBounds(PieChart pieChart, List<PieLabel> pls)
|
||||
{
|
||||
Rectangle r = pieChart.ContentBoundsEx;
|
||||
|
||||
for (int i = 0; i < pls.Count; i++)
|
||||
{
|
||||
PieLabel pl = pls[i];
|
||||
|
||||
if (pl.Bounds.IsEmpty == false)
|
||||
{
|
||||
int margin = Dpi.Width(pl.LabelStyle.LabelMargin);
|
||||
|
||||
if (pl.Bounds.Bottom + margin > r.Bottom)
|
||||
{
|
||||
Rectangle t = pl.Bounds;
|
||||
t.Y = (r.Bottom - t.Height - margin);
|
||||
pl.Bounds = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region SortLabels
|
||||
|
||||
private List<PieLabel>[] SortLabels()
|
||||
{
|
||||
List<PieLabel>[] plist = new List<PieLabel>[2];
|
||||
|
||||
plist[0] = new List<PieLabel>();
|
||||
plist[1] = new List<PieLabel>();
|
||||
|
||||
foreach (PieLabel pl in _PieLabels)
|
||||
{
|
||||
double angle = pl.PieSeriesPoint.CenterAngle % 360;
|
||||
|
||||
pl.IsRightlabel = (angle >= 270 || angle <= 90);
|
||||
|
||||
if (pl.IsRightlabel == true)
|
||||
plist[1].Add(pl);
|
||||
else
|
||||
plist[0].Add(pl);
|
||||
}
|
||||
|
||||
plist[0].Sort(new PieLabelYComparer());
|
||||
plist[1].Sort(new PieLabelYComparer());
|
||||
|
||||
return (plist);
|
||||
}
|
||||
|
||||
#region PieLabelYComparer
|
||||
|
||||
private class PieLabelYComparer : IComparer<PieLabel>
|
||||
{
|
||||
public int Compare(PieLabel pl1, PieLabel pl2)
|
||||
{
|
||||
return (pl1.PtSliceEdge.Y - pl2.PtSliceEdge.Y);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsAnyOverlap
|
||||
|
||||
private bool IsAnyOverlap(PieChart pieChart, List<PieLabel> pls)
|
||||
{
|
||||
if (pls.Count <= 0)
|
||||
return (false);
|
||||
|
||||
PieSeriesPoint psp = pls[0].PieSeriesPoint;
|
||||
|
||||
if (psp.SliceLabelVisibilityEx == SliceLabelVisibility.SliceMouseOver)
|
||||
return (false);
|
||||
|
||||
int maxy = 0;
|
||||
|
||||
for (int i = 0; i < pls.Count; i++)
|
||||
{
|
||||
PieLabel pl = pls[i];
|
||||
|
||||
if (pl.Bounds.IsEmpty == false)
|
||||
{
|
||||
if (maxy > pl.Bounds.Y)
|
||||
return (IsAnyOverlapEx(pieChart, pls));
|
||||
|
||||
int margin = Dpi.Width(pl.LabelStyle.LabelMargin);
|
||||
|
||||
if (pl.Bounds.Bottom + margin > maxy)
|
||||
maxy = pl.Bounds.Bottom + margin;
|
||||
}
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
#region IsAnyOverlapEx
|
||||
|
||||
private bool IsAnyOverlapEx(PieChart pieChart, List<PieLabel> pls)
|
||||
{
|
||||
for (int i = 0; i < pls.Count; i++)
|
||||
{
|
||||
PieLabel pl = pls[i];
|
||||
|
||||
if (pl.Bounds.IsEmpty == false)
|
||||
{
|
||||
int margin = pl.LabelStyle.LabelMargin;
|
||||
|
||||
Rectangle r = pl.Bounds;
|
||||
r.Inflate(margin, margin);
|
||||
|
||||
for (int j = i + 1; j < pls.Count; j++)
|
||||
{
|
||||
PieLabel pl2 = pls[j];
|
||||
|
||||
if (r.IntersectsWith(pl2.Bounds) == true)
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region HideOverLapping
|
||||
|
||||
private void HideOverLapping(List<PieLabel> pls, Rectangle bounds)
|
||||
{
|
||||
for (int i = 0; i < pls.Count; i++)
|
||||
{
|
||||
PieLabel pl = pls[i];
|
||||
|
||||
if (pl.Bounds.IsEmpty == false)
|
||||
{
|
||||
for (int j = i + 1; j < pls.Count; j++)
|
||||
{
|
||||
PieLabel pl2 = pls[j];
|
||||
|
||||
if (pl.Bounds.IntersectsWith(pl2.Bounds) == true)
|
||||
pl2.Bounds = Rectangle.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region AdjustUpwards
|
||||
|
||||
private void AdjustUpwards(PieChart pieChart, List<PieLabel> pls, Rectangle bounds)
|
||||
{
|
||||
for (int i = pls.Count - 1; i > 0; i--)
|
||||
{
|
||||
PieLabel pl0 = pls[i];
|
||||
PieLabel pl1 = pls[i - 1];
|
||||
|
||||
int margin = Dpi.Width(pl0.LabelStyle.LabelMargin);
|
||||
|
||||
Rectangle t = pl0.Bounds;
|
||||
t.Inflate(margin, margin);
|
||||
|
||||
if (pl1.Bounds.Bottom > t.Y)
|
||||
{
|
||||
if ((pl1.Bounds.X < t.Right) && (t.X < pl1.Bounds.Right))
|
||||
{
|
||||
Rectangle r = pl1.Bounds;
|
||||
|
||||
r.Y = Math.Max(bounds.Y + margin, pl0.Bounds.Y - pl1.Bounds.Height - margin);
|
||||
|
||||
pl1.Bounds = r;
|
||||
|
||||
AdjustForPieIntersect(pl1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region AdjustDownwards
|
||||
|
||||
private void AdjustDownwards(PieChart pieChart, List<PieLabel> pls, Rectangle bounds)
|
||||
{
|
||||
for (int i = 0; i < pls.Count - 1; i++)
|
||||
{
|
||||
PieLabel pl0 = pls[i];
|
||||
PieLabel pl1 = pls[i + 1];
|
||||
|
||||
int margin = Dpi.Width(pl0.LabelStyle.LabelMargin) + 4;
|
||||
|
||||
Rectangle t = pl0.Bounds;
|
||||
t.Inflate(margin, margin);
|
||||
|
||||
if (pl1.Bounds.Bottom < t.Bottom)
|
||||
{
|
||||
if ((pl1.Bounds.X < t.Right) && (t.X < pl1.Bounds.Right))
|
||||
{
|
||||
Rectangle r = pl1.Bounds;
|
||||
|
||||
r.Y = Math.Min(bounds.Bottom - r.Height - margin, t.Bottom);
|
||||
|
||||
pl1.Bounds = r;
|
||||
|
||||
AdjustForPieIntersect(pl1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region AdjustSpread
|
||||
|
||||
private void AdjustSpread(List<PieLabel> pls, Rectangle bounds)
|
||||
{
|
||||
int height = 0;
|
||||
|
||||
for (int i = 0; i < pls.Count; i++)
|
||||
height += pls[i].Bounds.Height;
|
||||
|
||||
int margin = bounds.Height - height;
|
||||
|
||||
if (pls.Count > 1)
|
||||
margin /= (pls.Count - 1);
|
||||
|
||||
int y = bounds.Y;
|
||||
|
||||
for (int i = 0; i < pls.Count; i++)
|
||||
{
|
||||
PieLabel pl = pls[i];
|
||||
|
||||
Rectangle r = pl.Bounds;
|
||||
|
||||
r.Y = y;
|
||||
pl.Bounds = r;
|
||||
|
||||
y = (pl.Bounds.Bottom + margin);
|
||||
|
||||
AdjustForPieIntersect(pl);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region AdjustLabelSizes
|
||||
|
||||
private void AdjustLabelSizes(Graphics g,
|
||||
PieChart pieChart, List<PieLabel> pls, Rectangle bounds)
|
||||
{
|
||||
Rectangle r = pieChart.ContentBoundsEx;
|
||||
|
||||
foreach (PieLabel pl in pls)
|
||||
{
|
||||
PieSeriesPoint psp = pl.PieSeriesPoint;
|
||||
|
||||
ChartSliceVisualStyle sstyle =
|
||||
psp.GetEffectiveSliceStyle(pieChart, psp.ChartSeries);
|
||||
|
||||
Rectangle t = GetChartBounds(pieChart, pl);
|
||||
|
||||
if (pl.LabelSize.Width != t.Width)
|
||||
{
|
||||
PieSeries series = psp.ChartSeries;
|
||||
|
||||
Size size = series.MeasurePieLabel(g,
|
||||
pieChart, psp, pl, t.Width, sstyle.SliceOuterLabelStyle);
|
||||
|
||||
if (size != pl.Bounds.Size)
|
||||
{
|
||||
if (t.X != pl.Bounds.X && size.Width < t.Size.Width)
|
||||
t.X += (t.Size.Width - size.Width);
|
||||
|
||||
if (size.Height > t.Size.Height)
|
||||
t.Y -= (size.Height - t.Size.Height) / 2;
|
||||
|
||||
t.Size = size;
|
||||
}
|
||||
|
||||
pl.Bounds = t;
|
||||
|
||||
AdjustForPieIntersect(pl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region GetChartBounds
|
||||
|
||||
private Rectangle GetChartBounds(PieChart pieChart, PieLabel pl)
|
||||
{
|
||||
Rectangle r = pl.Bounds;
|
||||
|
||||
r.Inflate(4, 4);
|
||||
|
||||
if (r.X < pieChart.ContentBoundsEx.X)
|
||||
{
|
||||
r.Width -= (pieChart.ContentBoundsEx.X - r.X);
|
||||
r.X = pieChart.ContentBoundsEx.X;
|
||||
|
||||
if (r.Width <= 0)
|
||||
return (Rectangle.Empty);
|
||||
}
|
||||
|
||||
if (r.Right >= pieChart.ContentBoundsEx.Right)
|
||||
{
|
||||
r.Width -= (r.Right - pieChart.ContentBoundsEx.Right + 1);
|
||||
|
||||
if (r.Width <= 0)
|
||||
return (Rectangle.Empty);
|
||||
}
|
||||
|
||||
if (r.Y < pieChart.ContentBoundsEx.Y)
|
||||
{
|
||||
r.Height -= (pieChart.ContentBoundsEx.Y - r.Y);
|
||||
r.Y = pieChart.ContentBoundsEx.Y;
|
||||
|
||||
if (r.Height <= 0)
|
||||
return (Rectangle.Empty);
|
||||
}
|
||||
|
||||
if (r.Bottom >= pieChart.ContentBoundsEx.Bottom)
|
||||
{
|
||||
int n = (r.Bottom - pieChart.ContentBoundsEx.Bottom + 1);
|
||||
|
||||
r.Y -= n;
|
||||
r.Width++;
|
||||
|
||||
if (r.Height <= 0)
|
||||
return (Rectangle.Empty);
|
||||
}
|
||||
|
||||
r.Inflate(-4, -4);
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region UpdateBoxPoints
|
||||
|
||||
private void UpdateBoxPoints(PieChart pieChart, List<PieLabel> pls)
|
||||
{
|
||||
foreach (PieLabel pl in pls)
|
||||
{
|
||||
Rectangle t = new Rectangle();
|
||||
|
||||
Rectangle r = pl.Bounds;
|
||||
|
||||
if (r.IsEmpty == false)
|
||||
{
|
||||
if (pl.LabelStyle.DrawConnector == Tbool.True)
|
||||
{
|
||||
int tick = pl.LabelStyle.ConnectorTickLength;
|
||||
|
||||
if (pl.IsLeftlabel == true)
|
||||
{
|
||||
pl.PtBoxEdge = new Point(r.Right, r.Y + r.Height / 2);
|
||||
pl.PtBoxBend = new Point(pl.PtBoxEdge.X + tick, pl.PtBoxEdge.Y);
|
||||
}
|
||||
else
|
||||
{
|
||||
pl.PtBoxEdge = new Point(r.X, r.Y + r.Height / 2);
|
||||
pl.PtBoxBend = new Point(pl.PtBoxEdge.X - tick, pl.PtBoxEdge.Y);
|
||||
}
|
||||
|
||||
Point ptMin = new Point();
|
||||
Point ptMax = new Point();
|
||||
|
||||
if (pl.PtBoxEdge.X < pl.PtSliceEdge.X)
|
||||
{
|
||||
ptMin.X = pl.PtBoxEdge.X;
|
||||
ptMax.X = pl.PtSliceEdge.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptMin.X = pl.PtSliceEdge.X;
|
||||
ptMax.X = pl.PtBoxEdge.X;
|
||||
}
|
||||
|
||||
if (pl.PtBoxEdge.Y < pl.PtSliceEdge.Y)
|
||||
{
|
||||
ptMin.Y = pl.PtBoxEdge.Y;
|
||||
ptMax.Y = pl.PtSliceEdge.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptMin.Y = pl.PtSliceEdge.Y;
|
||||
ptMax.Y = pl.PtBoxEdge.Y;
|
||||
}
|
||||
|
||||
t.Location = ptMin;
|
||||
t.Width = ptMax.X - ptMin.X + 1;
|
||||
t.Height = ptMax.Y - ptMin.Y + 1;
|
||||
}
|
||||
}
|
||||
|
||||
pl.Bounds = r;
|
||||
pl.ConnectorBounds = t;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user