DotNet 4.8.1 build of DotNetBar

This commit is contained in:
2025-02-07 10:35:23 -05:00
parent 33439b63a0
commit 6b0a5d60f4
2609 changed files with 989814 additions and 7 deletions

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}