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,814 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Windows.Forms;
using DevComponents.DotNetBar.Charts.Style;
namespace DevComponents.DotNetBar.Charts
{
/// <summary>
/// Represents the collection of Axis Stripes.
/// </summary>
[Editor("DevComponents.Charts.Design.AxisStripeCollectionEditor, DevComponents.Charts.Design, " +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public class AxisStripeCollection : CustomNamedCollection<AxisStripe>
{
public AxisStripeCollection()
{
}
#region GetUniqueName
public string GetUniqueName()
{
return (GetUniqueName("Stripe"));
}
#endregion
}
/// <summary>
/// Element describing a color stripe on the chart. Each AxisStripe
/// is associated with a primary or Ancillary Axis.
/// </summary>
public class AxisStripe : ChartVisualElement, ILegendItem
{
#region Private variables
private States _States;
private object _MinValue;
private object _MaxValue;
private AxisStripeVisualStyle _AxisStripeVisualStyle;
private string _LegendText;
private ChartLegendItem _LegendItem;
private ChartLegendItemVisualStyles _ChartLegendItemVisualStyles;
#endregion
#region Constructors
/// <summary>
/// Create a new AxisStripe.
/// </summary>
/// <param name="name"></param>
/// <param name="minValue"></param>
/// <param name="maxValue"></param>
public AxisStripe(string name, object minValue, object maxValue)
: this()
{
Name = name;
MinValue = minValue;
MaxValue = maxValue;
}
/// <summary>
/// Create a new AxisStripe.
/// </summary>
/// <param name="name"></param>
public AxisStripe(string name)
: this()
{
Name = name;
}
/// <summary>
/// Create a new AxisStripe.
/// </summary>
public AxisStripe()
{
InitDefaultStates();
}
#endregion
#region InitDefaultStates
private void InitDefaultStates()
{
SetState(States.CheckedInLegend, true);
SetState(States.ShowInLegend, true);
SetState(States.ShowInParentLegend, true);
SetState(States.ShowCheckBoxInLegend, true);
SetState(States.ShowMarkerInLegend, true);
}
#endregion
#region Public properties
#region AxisStripeVisualStyle
/// <summary>
/// Gets or sets the visual style for the AxisStripe.
/// </summary>
[Category("Style")]
[Description("Indicates the visual style for the AxisStripe.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public AxisStripeVisualStyle AxisStripeVisualStyle
{
get
{
if (_AxisStripeVisualStyle == null)
{
_AxisStripeVisualStyle = new AxisStripeVisualStyle();
StyleVisualChangeHandler(null, _AxisStripeVisualStyle);
}
return (_AxisStripeVisualStyle);
}
set
{
if (_AxisStripeVisualStyle != value)
{
AxisStripeVisualStyle oldValue = _AxisStripeVisualStyle;
_AxisStripeVisualStyle = value;
OnVisualStyleChanged("AxisStripeVisualStyle", oldValue, value);
if (oldValue != null)
oldValue.Dispose();
}
}
}
#endregion
#region IsDisplayed
///<summary>
/// Gets whether the Stripe is displayed (must be Visible
/// and appropriately 'checked' if presented in the Legend).
///</summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool IsDisplayed
{
get
{
return ((Visible == true) &&
(ShowCheckBoxInLegend == false || CheckedInLegend == true));
}
}
#endregion
#region MaxValue
///<summary>
/// Gets or sets the maximum axis stripe value.
///</summary>
[DefaultValue(null), Category("Data")]
[Description("Indicates the maximum axis stripe value.")]
[TypeConverter("DevComponents.Charts.Design.PointValueConverter, DevComponents.Charts.Design," +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf")]
public object MaxValue
{
get { return (_MaxValue); }
set
{
if (value != _MaxValue)
{
_MaxValue = value;
OnPropertyChangedEx("MaxValue", Style.VisualChangeType.Layout);
}
}
}
#endregion
#region MinValue
///<summary>
/// Gets or sets the minimum axis stripe value.
///</summary>
[DefaultValue(null), Category("Data")]
[Description("Indicates the minimum axis stripe value.")]
[TypeConverter("DevComponents.Charts.Design.PointValueConverter, DevComponents.Charts.Design," +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf")]
public object MinValue
{
get { return (_MinValue); }
set
{
if (value != _MinValue)
{
_MinValue = value;
OnPropertyChangedEx("MinValue", Style.VisualChangeType.Layout);
}
}
}
#endregion
#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)
{
}
#endregion
#region Style support
#region InvalidateStyle
///<summary>
///Invalidate the cached Styles
///</summary>
public void InvalidateStyle()
{
ClearEffectiveStyles();
}
#endregion
#region ClearEffectiveStyles
protected override void ClearEffectiveStyles()
{
base.ClearEffectiveStyles();
if (LegendItem != null)
LegendItem.EffectiveStyles.InvalidateStyles();
}
#endregion
#region StyleChanged
protected override void StyleChanged(object sender, PropertyChangedEventArgs e)
{
base.StyleChanged(sender, e);
if (sender is ChartLegendItemVisualStyles && LegendItem != null)
InvalidateRender(LegendItem.Bounds);
}
#endregion
#endregion
#region 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();
StyleVisualChangeHandler(null, _ChartLegendItemVisualStyles);
}
return (_ChartLegendItemVisualStyles);
}
set
{
if (_ChartLegendItemVisualStyles != value)
{
ChartLegendItemVisualStyles oldValue = _ChartLegendItemVisualStyles;
_ChartLegendItemVisualStyles = value;
OnStyleChanged("ChartLegendItemVisualStyles", oldValue, value);
if (oldValue != null)
oldValue.Dispose();
}
}
}
#endregion
#region CheckedInLegend
/// <summary>
/// Gets or sets whether the ReferenceLine is checked in the Legend.
/// </summary>
[DefaultValue(true), Category("Legend")]
[Description("Indicates whether the ReferenceLine is checked in the Legend.")]
public bool CheckedInLegend
{
get { return (TestState(States.CheckedInLegend)); }
set
{
if (value != CheckedInLegend)
{
SetState(States.CheckedInLegend, value);
if (LegendItem != null)
LegendItem.UpdateCheckState();
OnPropertyChangedEx("CheckedInLegend", VisualChangeType.Render);
}
}
}
#endregion
#region ShowCheckBoxInLegend
/// <summary>
/// Gets or sets whether a checkbox for the ReferenceLine is shown in the Legend.
/// </summary>
[DefaultValue(true), Category("Legend")]
[Description("Indicates whether a checkbox for the ReferenceLine 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 ReferenceLine is shown in the Legend.
/// </summary>
[DefaultValue(true), Category("Legend")]
[Description("Indicates whether the ReferenceLine 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 Reference Line is shown in parent Legend(s).
/// </summary>
[DefaultValue(true), Category("Legend")]
[Description("Indicates whether the Reference 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 ReferenceLine Marker is shown in the Legend.
/// </summary>
[DefaultValue(true), Category("Legend")]
[Description("Indicates whether the ReferenceLine 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 AxisStripe.
/// </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 = "(RefLine)";
_LegendItem.ChartItems.Add(this);
}
return (_LegendItem);
}
#endregion
#region GetLegendItems
/// <summary>
/// Creates a list of legend items associated with
/// the AxisStripe.
/// </summary>
/// <returns></returns>
public List<ChartLegendItem> GetLegendItems()
{
List<ChartLegendItem> list = null;
ChartLegendItem item = GetLegendItem();
if (item != null)
{
list = new List<ChartLegendItem>(1);
list.Add(item);
}
return (list);
}
#endregion
#region GetLegendItemColor
/// <summary>
/// Gets the default color associated with the
/// AxisStripe legend item.
/// </summary>
/// <returns></returns>
public Color GetLegendItemColor()
{
AxisStripeVisualStyle astyle = AxisStripeVisualStyle;
Color color = astyle.Background.Color1;
if (color.IsEmpty == false)
return (color);
return (Color.DimGray);
}
#endregion
#region RenderLegendItemMarker
/// <summary>
/// Renders the Legend item Marker.
/// </summary>
/// <param name="g"></param>
/// <param name="litem"></param>
/// <param name="style"></param>
public void RenderLegendItemMarker(Graphics g,
ChartLegendItem litem, ChartLegendItemVisualStyle style)
{
AxisStripeVisualStyle astyle = AxisStripeVisualStyle;
Rectangle bounds = litem.MarkerBounds;
if (astyle.Background.IsEmpty == true)
{
g.FillRectangle(Brushes.LightPink, bounds);
}
else
{
using (Brush br = astyle.Background.GetBrush(bounds))
g.FillRectangle(br, bounds);
}
}
#endregion
#endregion
#region Copy/CopyTo
/// <summary>
/// Creates a copy of the element.
/// </summary>
/// <returns></returns>
public override ChartVisualElement Copy()
{
AxisStripe copy = new AxisStripe();
CopyTo(copy);
return (copy);
}
/// <summary>
/// Copies the current element properties and styles
/// to the provided "copy".
/// </summary>
/// <param name="copy"></param>
public override void CopyTo(ChartVisualElement copy)
{
AxisStripe c = copy as AxisStripe;
if (c != null)
{
base.CopyTo(c);
c.AxisStripeVisualStyle = (_AxisStripeVisualStyle != null) ? _AxisStripeVisualStyle.Copy() : null;
c.ChartLegendItemVisualStyles = (_ChartLegendItemVisualStyles != null) ? ChartLegendItemVisualStyles.Copy() : null;
c.MaxValue = MaxValue;
c.MinValue = MinValue;
c.CheckedInLegend = CheckedInLegend;
c.ShowCheckBoxInLegend = ShowCheckBoxInLegend;
c.ShowInLegend = ShowInLegend;
c.ShowInParentLegend = ShowInParentLegend;
c.LegendText = LegendText;
c.ShowMarkerInLegend = ShowMarkerInLegend;
}
}
#endregion
#region GetSerialData
internal override SerialElementCollection GetSerialData(string serialName)
{
SerialElementCollection sec = new SerialElementCollection();
if (serialName != null)
{
if (serialName.Equals("") == true)
serialName = "ChartAxis";
sec.AddStartElement(serialName);
}
if (_AxisStripeVisualStyle != null && _AxisStripeVisualStyle.IsEmpty == false)
sec.AddElement(_AxisStripeVisualStyle.GetSerialData("AxisStripeVisualStyle"));
if (_ChartLegendItemVisualStyles != null)
sec.AddElement(_ChartLegendItemVisualStyles.GetSerialData("ChartLegendItemVisualStyles"));
sec.AddDataValue("MaxValue", MaxValue, null);
sec.AddDataValue("MinValue", MinValue, null);
sec.AddValue("CheckedInLegend", CheckedInLegend, true);
sec.AddValue("LegendText", LegendText, null);
sec.AddValue("ShowCheckBoxInLegend", ShowCheckBoxInLegend, true);
sec.AddValue("ShowInLegend", ShowInLegend, true);
sec.AddValue("ShowInParentLegend", ShowInParentLegend, true);
sec.AddValue("ShowMarkerInLegend", ShowMarkerInLegend, true);
sec.AddElement(base.GetSerialData(null));
if (serialName != null)
sec.AddEndElement(serialName);
return (sec);
}
#endregion
#region PutSerialData
#region ProcessValue
internal override void ProcessValue(SerialElement se)
{
switch (se.Name)
{
case "CheckedInLegend":
CheckedInLegend = bool.Parse(se.StringValue);
break;
case "LegendText":
LegendText = se.StringValue;
break;
case "MaxValue":
MaxValue = se.DataValue;
break;
case "MinValue":
MinValue = se.DataValue;
break;
case "ShowCheckBoxInLegend":
ShowCheckBoxInLegend = bool.Parse(se.StringValue);
break;
case "ShowInLegend":
ShowInLegend = bool.Parse(se.StringValue);
break;
case "ShowInParentLegend":
ShowInParentLegend = bool.Parse(se.StringValue);
break;
case "ShowMarkerInLegend":
ShowMarkerInLegend = bool.Parse(se.StringValue);
break;
default:
base.ProcessValue(se);
break;
}
}
#endregion
#region ProcessCollection
internal override void ProcessCollection(SerialElement se)
{
SerialElementCollection sec = se.Sec;
switch (se.Name)
{
case "AxisStripeVisualStyle":
sec.PutSerialData(AxisStripeVisualStyle);
break;
case "ChartLegendItemVisualStyles":
sec.PutSerialData(ChartLegendItemVisualStyles);
break;
default:
base.ProcessCollection(se);
break;
}
}
#region GetAncillaryAxis
private ChartAxis GetAncillaryAxis(ChartAxesCollection axes, string name)
{
foreach (ChartAxis axis in axes)
{
if (name.Equals(axis.Name) == true)
return (axis);
}
return (null);
}
#endregion
#endregion
#endregion
#region States
[Flags]
private enum States : uint
{
CheckedInLegend = (1U << 1),
ShowCheckBoxInLegend = (1U << 2),
ShowInLegend = (1U << 3),
ShowInParentLegend = (1U << 4),
ShowMarkerInLegend = (1U << 5),
}
#region TestState
private bool TestState(States state)
{
return ((_States & state) == state);
}
#endregion
#region SetState
private void SetState(States state, bool value)
{
if (value == true)
_States |= state;
else
_States &= ~state;
}
#endregion
#endregion
#region IDisposable
public override void Dispose()
{
AxisStripeVisualStyle = null;
base.Dispose();
}
#endregion
}
}

View File

@@ -0,0 +1,800 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using DevComponents.DotNetBar.Charts.Style;
namespace DevComponents.DotNetBar.Charts
{
#region ChartMajorGridLines
#region ChartMajorGridLinesX
/// <summary>
/// Represents a chart's MajorGridLines for the X-Axis.
/// </summary>
public class ChartMajorGridLinesX : ChartMajorGridLines
{
public ChartMajorGridLinesX()
: base(AxisOrientation.X)
{
}
#region RenderOverride
protected override void RenderOverride(ChartRenderInfo renderInfo)
{
if (Visible == true)
{
TickmarkTick[] ticks = TickmarkLayout.Ticks;
if (ticks != null)
{
Graphics g = renderInfo.Graphics;
ChartAxis axis = Parent as ChartAxis;
ChartXy chartXy = axis.Parent as ChartXy;
PieGridLineVisualStyle gstyle = EffectiveStyle;
Rectangle scContentBounds = GetScrollBounds(chartXy.ContentBounds);
if (gstyle.LinePattern != LinePattern.None &&
gstyle.LinePattern != LinePattern.NotSet && gstyle.LineWidth > 0)
{
using (Pen pen = new Pen(gstyle.LineColor, Dpi.Width(gstyle.LineWidth)))
{
pen.DashStyle = (DashStyle)gstyle.LinePattern;
Point pt = chartXy.GetLocalAdjustedPoint(Point.Empty);
foreach (TickmarkTick tmi in ticks)
{
Point pt1 = tmi.TickPoint;
pt1.X += pt.X;
pt1.Y = scContentBounds.Y;
Point pt2 = pt1;
pt2.Y = scContentBounds.Bottom;
g.DrawLine(pen, pt1, pt2);
}
}
}
}
}
}
#endregion
#region Copy/CopyTo
/// <summary>
/// Create a copy of the MajorGridLine.
/// </summary>
/// <returns></returns>
public override ChartVisualElement Copy()
{
ChartMajorGridLinesX copy = new ChartMajorGridLinesX();
CopyTo(copy);
return (copy);
}
/// <summary>
/// Copies the MajorGridLine to the given "copy".
/// </summary>
/// <param name="copy"></param>
public override void CopyTo(ChartVisualElement copy)
{
ChartMajorGridLinesX c = copy as ChartMajorGridLinesX;
if (c != null)
base.CopyTo(c);
}
#endregion
}
#endregion
#region ChartMajorGridLinesY
/// <summary>
/// Represents a chart's MajorGridLines for the Y-Axis.
/// </summary>
public class ChartMajorGridLinesY : ChartMajorGridLines
{
public ChartMajorGridLinesY()
: base(AxisOrientation.Y)
{
}
#region RenderOverride
protected override void RenderOverride(ChartRenderInfo renderInfo)
{
if (Visible == true)
{
TickmarkTick[] ticks = TickmarkLayout.Ticks;
if (ticks != null)
{
Graphics g = renderInfo.Graphics;
ChartAxis axis = Parent as ChartAxis;
ChartXy chartXy = axis.Parent as ChartXy;
PieGridLineVisualStyle gstyle = EffectiveStyle;
Rectangle scContentBounds = GetScrollBounds(chartXy.ContentBounds);
if (gstyle.LinePattern != LinePattern.None &&
gstyle.LinePattern != LinePattern.NotSet && gstyle.LineWidth > 0)
{
using (Pen pen = new Pen(gstyle.LineColor, Dpi.Height(gstyle.LineWidth)))
{
pen.DashStyle = (DashStyle)gstyle.LinePattern;
Point pt = chartXy.GetLocalAdjustedPoint(Point.Empty);
foreach (TickmarkTick tmi in ticks)
{
Point pt1 = tmi.TickPoint;
pt1.X = scContentBounds.X;
pt1.Y += pt.Y;
Point pt2 = pt1;
pt2.X = scContentBounds.Right;
g.DrawLine(pen, pt1, pt2);
}
}
}
}
}
}
#endregion
#region Copy/CopyTo
/// <summary>
/// Create a copy of the MajorGridLine.
/// </summary>
/// <returns></returns>
public override ChartVisualElement Copy()
{
ChartMajorGridLinesY copy = new ChartMajorGridLinesY();
CopyTo(copy);
return (copy);
}
/// <summary>
/// Copies the MajorGridLine to the given "copy".
/// </summary>
/// <param name="copy"></param>
public override void CopyTo(ChartVisualElement copy)
{
ChartMajorGridLinesY c = copy as ChartMajorGridLinesY;
if (c != null)
base.CopyTo(c);
}
#endregion
}
#endregion
#region ChartMajorGridLines
/// <summary>
/// Represents a chart's MajorGridLines.
/// </summary>
public class ChartMajorGridLines : ChartGridLines
{
public ChartMajorGridLines(AxisOrientation orientation)
: base(orientation)
{
}
}
#endregion
#endregion
#region ChartMinorGridLines
#region ChartMinorGridLinesX
public class ChartMinorGridLinesX : ChartMinorGridLines
{
public ChartMinorGridLinesX()
: base(AxisOrientation.X)
{
}
#region RenderOverride
protected override void RenderOverride(ChartRenderInfo renderInfo)
{
if (Visible == true)
{
TickmarkTick[] ticks = TickmarkLayout.Ticks;
if (ticks != null && ticks.Length > 1)
{
Graphics g = renderInfo.Graphics;
ChartAxis axis = Parent as ChartAxis;
ChartXy chartXy = axis.Parent as ChartXy;
PieGridLineVisualStyle gstyle = EffectiveStyle;
Rectangle scContentBounds = GetScrollBounds(chartXy.ContentBounds);
if (gstyle.LinePattern != LinePattern.None &&
gstyle.LinePattern != LinePattern.NotSet && gstyle.LineWidth > 0)
{
using (Pen pen = new Pen(gstyle.LineColor, Dpi.Width(gstyle.LineWidth)))
{
pen.DashStyle = (DashStyle)gstyle.LinePattern;
int minorTickCount = axis.MinorTickmarks.TickmarkCount;
Point pt = chartXy.GetLocalAdjustedPoint(Point.Empty);
for (int i = 0; i < ticks.Length - 1; i++)
{
TickmarkTick tick = ticks[i];
Point pt1 = tick.TickPoint;
pt1.Y = scContentBounds.Y;
Point pt2 = pt1;
pt2.Y = scContentBounds.Bottom;
double dx = (double)(ticks[i + 1].TickPoint.X - tick.TickPoint.X) / (minorTickCount + 1);
double ddx = dx;
for (int j = 0; j < minorTickCount; j++)
{
pt1.X = pt.X + (int)(tick.TickPoint.X + ddx);
pt2.X = pt1.X;
ddx += dx;
g.DrawLine(pen, pt1, pt2);
}
}
}
}
}
}
}
#endregion
#region Copy/CopyTo
/// <summary>
/// Create a copy of the MinorGridLine.
/// </summary>
/// <returns></returns>
public override ChartVisualElement Copy()
{
ChartMinorGridLinesX copy = new ChartMinorGridLinesX();
CopyTo(copy);
return (copy);
}
/// <summary>
/// Copies the MinorGridLine to the given "copy".
/// </summary>
/// <param name="copy"></param>
public override void CopyTo(ChartVisualElement copy)
{
ChartMinorGridLinesX c = copy as ChartMinorGridLinesX;
if (c != null)
base.CopyTo(c);
}
#endregion
}
#endregion
#region ChartMinorGridLinesY
public class ChartMinorGridLinesY : ChartMinorGridLines
{
public ChartMinorGridLinesY()
: base(AxisOrientation.Y)
{
}
#region RenderOverride
protected override void RenderOverride(ChartRenderInfo renderInfo)
{
if (Visible == true)
{
TickmarkTick[] ticks = TickmarkLayout.Ticks;
if (ticks != null)
{
Graphics g = renderInfo.Graphics;
ChartAxis axis = Parent as ChartAxis;
ChartXy chartXy = axis.Parent as ChartXy;
PieGridLineVisualStyle gstyle = EffectiveStyle;
Rectangle scContentBounds = GetScrollBounds(chartXy.ContentBounds);
if (gstyle.LinePattern != LinePattern.None &&
gstyle.LinePattern != LinePattern.NotSet && gstyle.LineWidth > 0)
{
using (Pen pen = new Pen(gstyle.LineColor, Dpi.Height(gstyle.LineWidth)))
{
pen.DashStyle = (DashStyle)gstyle.LinePattern;
int minorTickCount = axis.MinorTickmarks.TickmarkCount;
Point pt = chartXy.GetLocalAdjustedPoint(Point.Empty);
for (int i = 0; i < ticks.Length - 1; i++)
{
TickmarkTick tick = ticks[i];
Point pt1 = tick.TickPoint;
pt1.X = scContentBounds.X;
Point pt2 = pt1;
pt2.X = scContentBounds.Right;
double dy = (double)(ticks[i + 1].TickPoint.Y - tick.TickPoint.Y) / (minorTickCount + 1);
double ddy = dy;
for (int j = 0; j < axis.MinorTickmarks.TickmarkCount; j++)
{
pt1.Y = pt.Y + (int)(tick.TickPoint.Y + ddy);
pt2.Y = pt1.Y;
ddy += dy;
g.DrawLine(pen, pt1, pt2);
}
}
}
}
}
}
}
#endregion
#region Copy/CopyTo
/// <summary>
/// Create a copy of the MinorGridLine.
/// </summary>
/// <returns></returns>
public override ChartVisualElement Copy()
{
ChartMinorGridLinesY copy = new ChartMinorGridLinesY();
CopyTo(copy);
return (copy);
}
/// <summary>
/// Copies the MinorGridLine to the given "copy".
/// </summary>
/// <param name="copy"></param>
public override void CopyTo(ChartVisualElement copy)
{
ChartMinorGridLinesY c = copy as ChartMinorGridLinesY;
if (c != null)
base.CopyTo(c);
}
#endregion
}
#endregion
#region ChartMinorGridLines
public class ChartMinorGridLines : ChartGridLines
{
public ChartMinorGridLines(AxisOrientation orientation)
: base(orientation)
{
}
}
#endregion
#endregion
#region ChartGridLines
[TypeConverter(typeof(BlankExpandableObjectConverter))]
public abstract class ChartGridLines : ChartVisualElement
{
#region Private variables
private States _States;
private AxisOrientation _AxisOrientation;
private TickmarkLayout _TickmarkLayout;
private PieGridLineVisualStyle _GridLinesVisualStyle;
private EffectiveStyle<PieGridLineVisualStyle> _EffectiveStyle;
#endregion
public ChartGridLines(AxisOrientation orientation)
{
_AxisOrientation = orientation;
InitDefaultStates();
_EffectiveStyle = new EffectiveStyle<PieGridLineVisualStyle>(this);
}
#region InitDefaultStates
private void InitDefaultStates()
{
}
#endregion
#region Public properties
#region DisplayOnTop
/// <summary>
/// Gets or sets whether grid lines are displayed on top of chart data.
/// </summary>
[DefaultValue(false), Category("Appearance")]
[Description("Indicates whether grid lines are displayed on top of chart data.")]
public bool DisplayOnTop
{
get { return (TestState(States.DisplayOnTop)); }
set
{
if (value != DisplayOnTop)
{
SetState(States.DisplayOnTop, value);
OnPropertyChangedEx("DisplayOnTop", VisualChangeType.Render);
}
}
}
#endregion
#region EffectiveStyles
/// <summary>
/// Gets a reference to the GridLine's Effective (cached, composite) style.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public PieGridLineVisualStyle EffectiveStyle
{
get { return (_EffectiveStyle.Style); }
}
#endregion
#region GridLinesVisualStyle
/// <summary>
/// Gets or sets the visual style for the GridLines.
/// </summary>
[Category("Style")]
[Description("Indicates the visual style for the GridLines.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public PieGridLineVisualStyle GridLinesVisualStyle
{
get
{
if (_GridLinesVisualStyle == null)
{
_GridLinesVisualStyle = new PieGridLineVisualStyle();
StyleVisualChangeHandler(null, _GridLinesVisualStyle);
}
return (_GridLinesVisualStyle);
}
set
{
if (_GridLinesVisualStyle != value)
{
PieGridLineVisualStyle oldValue = _GridLinesVisualStyle;
_GridLinesVisualStyle = value;
OnVisualStyleChanged("GridLinesVisualStyle", oldValue, value);
if (oldValue != null)
oldValue.Dispose();
}
}
}
#endregion
#endregion
#region Internal properties
#region TickmarkLayout
internal TickmarkLayout TickmarkLayout
{
get { return (_TickmarkLayout); }
set { _TickmarkLayout = value; }
}
#endregion
#endregion
#region MeasureOverride
protected override void MeasureOverride(ChartLayoutInfo layoutInfo)
{
}
#endregion
#region ArrangeOverride
protected override void ArrangeOverride(ChartLayoutInfo layoutInfo)
{
BoundsRelative = layoutInfo.LayoutBounds;
}
#endregion
#region RenderOverride
protected override void RenderOverride(ChartRenderInfo renderInfo)
{
}
#endregion
#region Render
internal override void Render(ChartRenderInfo renderInfo)
{
if (Displayed == true)
{
Rectangle bounds = BoundsRelative;
if (renderInfo.ClipRectangle.IntersectsWith(bounds))
RenderOverride(renderInfo);
}
}
#endregion
#region Style handling
#region ApplyStyles
public override void ApplyStyles(BaseVisualStyle style)
{
PieGridLineVisualStyle sstyle = style as PieGridLineVisualStyle;
if (sstyle != null)
{
ApplyParentStyles(sstyle, Parent as ChartContainer);
sstyle.ApplyStyle(GridLinesVisualStyle);
if (sstyle.LineColor.IsEmpty == true)
{
if (this is ChartMajorGridLines)
sstyle.LineColor = Color.DimGray;
else
sstyle.LineColor = Color.LightGray;
}
if (sstyle.LinePattern == LinePattern.NotSet)
sstyle.LinePattern = LinePattern.Solid;
if (sstyle.LineWidth < 0)
sstyle.LineWidth = 1;
}
}
#region ApplyParentStyles
private void ApplyParentStyles(PieGridLineVisualStyle pstyle, ChartContainer item)
{
if (item != null)
{
ApplyParentStyles(pstyle, item.Parent as ChartContainer);
if (item is ChartPanel)
{
pstyle.ApplyStyle(((ChartPanel)item).DefaultVisualStyles.GridLineVisualStyle);
}
}
else
{
pstyle.ApplyStyle(ChartControl.BaseVisualStyles.GridLineVisualStyle);
pstyle.ApplyStyle(ChartControl.DefaultVisualStyles.GridLineVisualStyle);
}
}
#endregion
#endregion
#region ClearEffectiveStyles
protected override void ClearEffectiveStyles()
{
base.ClearEffectiveStyles();
if (_EffectiveStyle.InvalidateStyle() == true)
InvalidateLayout();
}
#endregion
#endregion
#region Copy/CopyTo
/// <summary>
/// Copies the chart element to the given "copy".
/// </summary>
/// <param name="copy"></param>
public override void CopyTo(ChartVisualElement copy)
{
ChartGridLines c = copy as ChartGridLines;
if (c != null)
{
base.CopyTo(c);
c.DisplayOnTop = DisplayOnTop;
c.GridLinesVisualStyle = (_GridLinesVisualStyle != null) ? GridLinesVisualStyle.Copy() : null;
}
}
#endregion
#region GetSerialData
internal override SerialElementCollection GetSerialData(string serialName)
{
SerialElementCollection sec = new SerialElementCollection();
if (serialName != null)
{
if (serialName.Equals("") == true)
serialName = "ChartGridLines";
sec.AddStartElement(serialName);
}
sec.AddValue("DisplayOnTop", DisplayOnTop, false);
if (_GridLinesVisualStyle != null && _GridLinesVisualStyle.IsEmpty == false)
sec.AddElement(_GridLinesVisualStyle.GetSerialData("GridLinesVisualStyle"));
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 "DisplayOnTop":
DisplayOnTop = bool.Parse(se.StringValue);
break;
default:
base.ProcessValue(se);
break;
}
}
#endregion
#region ProcessCollection
internal override void ProcessCollection(SerialElement se)
{
SerialElementCollection sec = se.Sec;
switch (se.Name)
{
case "GridLinesVisualStyle":
sec.PutSerialData(GridLinesVisualStyle);
break;
default:
base.ProcessCollection(se);
break;
}
}
#endregion
#endregion
#region States
[Flags]
private enum States : uint
{
DisplayOnTop = (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 override void Dispose()
{
GridLinesVisualStyle = null;
base.Dispose();
}
#endregion
}
#endregion
}

View File

@@ -0,0 +1,922 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using DevComponents.DotNetBar.Charts.Style;
namespace DevComponents.DotNetBar.Charts
{
class FlockAlign
{
#region Constants
private const long RemovePenalty = 1;
private const int MovesPerIteration = 500;
#endregion
#region Private variables
private List<PointLabelGroup> _LabelGroups;
#endregion
public FlockAlign(List<PointLabelGroup> labelGroups)
{
_LabelGroups = labelGroups;
foreach (PointLabelGroup lg in _LabelGroups)
{
foreach (PointLabel pl in lg.PointLabels)
pl.Bounds = Rectangle.Empty;
}
}
#region Iterate
public bool Iterate(Rectangle bounds, DataLabelOverlapMode ovlMode)
{
if (ovlMode == DataLabelOverlapMode.NotSet)
ovlMode = DataLabelOverlapMode.RotateAroundPoint;
for (int i = 0; i < _LabelGroups.Count; i++)
{
PointLabelGroup lg = _LabelGroups[i];
List<PointLabel> lps = lg.PointLabels;
ChartSeries series = lg.ChartSeries;
Point lp = Point.Empty;
for (int j = 0; j < lps.Count; j++)
{
PointLabel pl = lps[j];
if (pl.Visible == true )
{
DataLabelVisualStyle dstyle = pl.DataLabelVisualStyle ?? series.EffectiveDataLabelStyle;
if (series.IsBarSeries == true)
{
if (series.IsRotated == true)
IterateHBar(series, pl, bounds, ovlMode, dstyle);
else
IterateVBar(series, pl, bounds, ovlMode, dstyle);
}
else
{
IteratePoint(series, pl, bounds, lp, ovlMode, dstyle);
}
}
lp = pl.Point;
}
}
return (true);
}
#region IterateHBar
private void IterateHBar(ChartSeries series, PointLabel pl,
Rectangle bounds, DataLabelOverlapMode ovlMode, DataLabelVisualStyle dstyle)
{
ChartXy chartXy = series.Parent as ChartXy;
int start = (pl.IsDataLabel == true)
? pl.Point.X - 1 : series.GetHBarStart(chartXy, pl.SeriesPoint);
int end = pl.Point.X;
BarLabelPosition labelPos = pl.BarLabelPosition;
if (labelPos == BarLabelPosition.NotSet)
labelPos = series.GetBarLabelPosition(chartXy);
switch (labelPos)
{
case BarLabelPosition.Near:
SetHBarLabelNear(series, pl, bounds, ovlMode, dstyle, start, end, false);
break;
case BarLabelPosition.NearInside:
SetHBarLabelNear(series, pl, bounds, ovlMode, dstyle, start, end, true);
break;
case BarLabelPosition.Far:
SetHBarLabelFar(series, pl, bounds, ovlMode, dstyle, start, end, false);
break;
case BarLabelPosition.FarInside:
SetHBarLabelFar(series, pl, bounds, ovlMode, dstyle, start, end, true);
break;
default:
SetHBarLabelCenter(series, pl, bounds, ovlMode, dstyle, start, end);
break;
}
}
#region SetHBarLabelNear
private void SetHBarLabelNear(ChartSeries series, PointLabel pl, Rectangle bounds,
DataLabelOverlapMode ovlMode, DataLabelVisualStyle dstyle, int start, int end, bool inside)
{
ConnectorLineVisualStyle cstyle = dstyle.ConnectorLineStyle;
Point pt = new Point(start, pl.Point.Y + series.BarOffset);
Size size = GetBoundsSize(series, pl, dstyle);
Rectangle t = Rectangle.Empty;
int minLength = Dpi.Width(cstyle.MinLength);
for (int i = 0; i < 2; i++)
{
int clen = (inside == false && minLength > 0) ? minLength + Dpi.Width2 : Dpi.Width4;
int step = cstyle.LengthStep;
int offset = (size.Width / 2 + clen);
if (inside ? end < start : end > start)
{
step *= -1;
offset *= -1;
}
Point ptc = pt;
ptc.X += offset;
t = GetCenteredRectangle(series, ptc, size);
while (step < 0 ? t.X > bounds.X : t.Right < bounds.Right)
{
if (SetHBarLabelPos(pl, ovlMode, bounds, ptc, t, start, end) == true)
return;
if (ovlMode != DataLabelOverlapMode.RotateAroundPoint)
break;
t.X += step;
if (cstyle.MaxLength > 0)
{
if (Math.Abs(t.X - ptc.X) > cstyle.MaxLength)
break;
}
}
inside = !inside;
}
SetHBarDefaultLabelPos(series, ref pl, pt, t, ovlMode, start, end);
}
#endregion
#region SetHBarLabelFar
private void SetHBarLabelFar(ChartSeries series, PointLabel pl, Rectangle bounds,
DataLabelOverlapMode ovlMode, DataLabelVisualStyle dstyle, int start, int end, bool inside)
{
ConnectorLineVisualStyle cstyle = dstyle.ConnectorLineStyle;
Point pt = new Point(end, pl.Point.Y + series.BarOffset);
Size size = GetBoundsSize(series, pl, dstyle);
Rectangle t = Rectangle.Empty;
int minLength = Dpi.Width(cstyle.MinLength);
for (int i = 0; i < 2; i++)
{
int clen = (inside == false && minLength >= 0) ? minLength + Dpi.Width2 : Dpi.Width4;
int step = cstyle.LengthStep;
int offset = (size.Width / 2 + clen);
if (inside ? end > start : end < start)
{
step *= -1;
offset *= -1;
}
Point ptc = pt;
ptc.X += offset;
t = GetCenteredRectangle(series, ptc, size);
while (step < 0 ? t.X > bounds.X : t.Right < bounds.Right)
{
if (SetHBarLabelPos(pl, ovlMode, bounds, ptc, t, start, end) == true)
return;
if (ovlMode != DataLabelOverlapMode.RotateAroundPoint)
break;
t.X += step;
if (cstyle.MaxLength > 0)
{
if (Math.Abs(t.X - ptc.X) > cstyle.MaxLength)
break;
}
}
inside = !inside;
}
SetHBarDefaultLabelPos(series, ref pl, pt, t, ovlMode, start, end);
}
#endregion
#region SetHBarLabelCenter
private void SetHBarLabelCenter(ChartSeries series, PointLabel pl,
Rectangle bounds, DataLabelOverlapMode ovlMode, DataLabelVisualStyle dstyle,
int start, int end)
{
Point pt = new Point((end + start) / 2, pl.Point.Y + series.BarOffset);
int pass = 0;
int step = 2;
int startx = pt.X;
Size size = GetBoundsSize(series, pl, dstyle);
Rectangle t = GetCenteredRectangle(series, pt, size);
int len = (end + start) / 2;
while (pass <= len)
{
if (SetHBarLabelPos(pl, ovlMode, bounds, pt, t, start, end) == true)
return;
if (ovlMode != DataLabelOverlapMode.RotateAroundPoint)
break;
int pval = pass / 2 + 1;
if (pass % 2 > 0)
pval = -pval;
t.X = (startx + (pval * step));
pass++;
}
SetHBarDefaultLabelPos(series, ref pl, pt, t, ovlMode, start, end);
}
#endregion
#region SetHBarLabelPos
private bool SetHBarLabelPos(PointLabel pl,
DataLabelOverlapMode ovlMode, Rectangle bounds, Point pt, Rectangle t, int start, int end)
{
if (IsFreeArea(t, bounds, ovlMode, false, true) == true)
{
pl.Bounds = t;
SetHBarEdgePoint(pl, pt, t, start, end);
return (true);
}
if (ovlMode == DataLabelOverlapMode.HideOverlapping)
return (true);
return (false);
}
#endregion
#region SetHBarDefaultLabelPos
private void SetHBarDefaultLabelPos(ChartSeries series, ref PointLabel pl,
Point pt, Rectangle t, DataLabelOverlapMode ovlMode, int start, int end)
{
if (ovlMode == DataLabelOverlapMode.RotateAroundPoint)
{
if (t.X < start)
t.X = start + Dpi.Width4;
else
t.X = end - (t.Width + Dpi.Width4);
ChartXy chartXy = series.Parent as ChartXy;
Rectangle bounds = chartXy.ContentBoundsEx;
if (t.Right > bounds.Right)
t.X -= (t.Right - bounds.Right + Dpi.Width4);
if (t.X < bounds.X)
t.X = bounds.X + Dpi.Width4;
pl.Bounds = t;
SetHBarEdgePoint(pl, pt, t, start, end);
}
else
{
pl.Bounds = Rectangle.Empty;
pl.EdgePoint = Point.Empty;
}
}
#endregion
#region SetHBarEdgePoint
private void SetHBarEdgePoint(PointLabel pl, Point pt, Rectangle t, int start, int end)
{
if (t.X > start && t.X > end)
{
pt.X = Math.Max(start, end);
pl.EdgePoint = new Point(t.X, pt.Y);
}
else if (t.X < start && t.X < end)
{
pt.X = Math.Min(start, end);
pl.EdgePoint = new Point(t.Right, pt.Y);
}
else
{
pl.EdgePoint = Point.Empty;
}
pl.Point = pt;
}
#endregion
#endregion
#region IterateVBar
private void IterateVBar(ChartSeries series, PointLabel pl,
Rectangle bounds, DataLabelOverlapMode ovlMode, DataLabelVisualStyle dstyle)
{
ChartXy chartXy = series.Parent as ChartXy;
int start = series.GetVBarStart(chartXy, pl.SeriesPoint);
int end = pl.Point.Y;
BarLabelPosition labelPos = series.GetBarLabelPosition(chartXy);
switch (labelPos)
{
case BarLabelPosition.Near:
SetVBarLabelNear(series, pl, bounds, ovlMode, dstyle, start, end, false);
break;
case BarLabelPosition.NearInside:
SetVBarLabelNear(series, pl, bounds, ovlMode, dstyle, start, end, true);
break;
case BarLabelPosition.Far:
SetVBarLabelFar(series, pl, bounds, ovlMode, dstyle, start, end, false);
break;
case BarLabelPosition.FarInside:
SetVBarLabelFar(series, pl, bounds, ovlMode, dstyle, start, end, true);
break;
default:
SetVBarLabelCenter(series, pl, bounds, ovlMode, dstyle, start, end);
break;
}
}
#region SetVBarLabelNear
private void SetVBarLabelNear(ChartSeries series, PointLabel pl, Rectangle bounds,
DataLabelOverlapMode ovlMode, DataLabelVisualStyle dstyle, int start, int end, bool inside)
{
ConnectorLineVisualStyle cstyle = dstyle.ConnectorLineStyle;
Point pt = new Point(pl.Point.X + series.BarOffset, start);
Size size = GetBoundsSize(series, pl, dstyle);
int minLength = Dpi.Width(cstyle.MinLength);
int clen = (inside == false && minLength >= 0) ? minLength + Dpi.Width2 : Dpi.Width4;
int step = cstyle.LengthStep;
int offset = (size.Height / 2 + clen);
Rectangle t = Rectangle.Empty;
for (int i = 0; i < 2; i++)
{
if (inside ? end < start : end > start)
{
step *= -1;
offset *= -1;
}
Point ptc = pt;
ptc.Y += offset;
t = GetCenteredRectangle(series, ptc, size);
while (t.Y < bounds.Bottom)
{
if (SetVBarLabelPos(pl, ovlMode, bounds, ptc, t, start, end) == true)
return;
if (ovlMode != DataLabelOverlapMode.RotateAroundPoint)
break;
t.Y += step;
if (cstyle.MaxLength > 0)
{
if (Math.Abs(t.Y - ptc.Y) > cstyle.MaxLength)
break;
}
}
inside = !inside;
}
SetVBarDefaultLabelPos(series, ref pl, pt, t, ovlMode, start, end);
}
#endregion
#region SetVBarLabelFar
private void SetVBarLabelFar(ChartSeries series, PointLabel pl, Rectangle bounds,
DataLabelOverlapMode ovlMode, DataLabelVisualStyle dstyle, int start, int end, bool inside)
{
ConnectorLineVisualStyle cstyle = dstyle.ConnectorLineStyle;
Point pt = new Point(pl.Point.X + series.BarOffset, end);
Size size = GetBoundsSize(series, pl, dstyle);
int minLength = Dpi.Width(cstyle.MinLength);
Rectangle t = Rectangle.Empty;
for (int i = 0; i < 2; i++)
{
int clen = (inside == false && minLength >= 0) ? minLength + Dpi.Width2 : Dpi.Width4;
int step = cstyle.LengthStep;
int offset = (size.Height / 2 + clen);
if (inside ? end > start : end < start)
{
step *= -1;
offset *= -1;
}
Point ptc = pt;
ptc.Y += offset;
t = GetCenteredRectangle(series, ptc, size);
while (step < 0 ? t.Y > bounds.Y : t.Y < bounds.Bottom)
{
if (SetVBarLabelPos(pl, ovlMode, bounds, ptc, t, start, end) == true)
return;
if (ovlMode != DataLabelOverlapMode.RotateAroundPoint)
break;
t.Y += step;
if (cstyle.MaxLength > 0)
{
if (Math.Abs(t.Y - ptc.Y) > cstyle.MaxLength)
break;
}
}
inside = !inside;
}
SetVBarDefaultLabelPos(series, ref pl, pt, t, ovlMode, start, end);
}
#endregion
#region SetVBarLabelCenter
private void SetVBarLabelCenter(ChartSeries series, PointLabel pl,
Rectangle bounds, DataLabelOverlapMode ovlMode, DataLabelVisualStyle dstyle,
int origin, int end)
{
Point pt = new Point(pl.Point.X + series.BarOffset, (end + origin) / 2);
int pass = 0;
int step = 2;
int starty = pt.Y;
Size size = GetBoundsSize(series, pl, dstyle);
Rectangle t = GetCenteredRectangle(series, pt, size);
int len = (end + origin) / 2;
while (pass <= len)
{
if (SetVBarLabelPos(pl, ovlMode, bounds, pt, t, origin, end) == true)
return;
if (ovlMode != DataLabelOverlapMode.RotateAroundPoint)
break;
int pval = pass / 2 + 1;
if (pass % 2 > 0)
pval = -pval;
t.Y = (starty + (pval * step));
pass++;
}
SetVBarDefaultLabelPos(series, ref pl, pt, t, ovlMode, origin, end);
}
#endregion
#region SetVBarLabelPos
private bool SetVBarLabelPos(PointLabel pl,
DataLabelOverlapMode ovlMode, Rectangle bounds, Point pt, Rectangle t, int start, int end)
{
if (IsFreeArea(t, bounds, ovlMode, false, true) == true)
{
pl.Bounds = t;
SetVBarEdgePoint(pl, pt, t, start, end);
return (true);
}
if (ovlMode == DataLabelOverlapMode.HideOverlapping)
return (true);
return (false);
}
#endregion
#region SetVBarDefaultLabelPos
private void SetVBarDefaultLabelPos(ChartSeries series, ref PointLabel pl,
Point pt, Rectangle t, DataLabelOverlapMode ovlMode, int start, int end)
{
if (ovlMode == DataLabelOverlapMode.RotateAroundPoint)
{
if (t.Y > start)
t.Y = start - (t.Height + Dpi.Height4);
else
t.Y = end + Dpi.Height4;
ChartXy chartXy = series.Parent as ChartXy;
Rectangle bounds = chartXy.ContentBoundsEx;
if (t.Y > bounds.Bottom)
t.Y -= (t.Bottom - bounds.Bottom + Dpi.Height4);
if (t.Y < bounds.Y)
t.Y = bounds.Y + Dpi.Height4;
pl.Bounds = t;
SetVBarEdgePoint(pl, pt, t, start, end);
}
else
{
pl.Bounds = Rectangle.Empty;
pl.EdgePoint = Point.Empty;
}
}
#endregion
#region SetVBarEdgePoint
private void SetVBarEdgePoint(PointLabel pl, Point pt, Rectangle t, int start, int end)
{
if (t.Y > start && t.Y > end)
{
pt.Y = Math.Max(start, end);
pl.EdgePoint = new Point(pt.X, t.Y);
}
else if (t.Y < start && t.Y < end)
{
pt.Y = Math.Min(start, end);
pl.EdgePoint = new Point(pt.X, t.Bottom);
}
else
{
pl.EdgePoint = Point.Empty;
}
pl.Point = pt;
}
#endregion
#endregion
#region IteratePoint
private void IteratePoint(ChartSeries series, PointLabel pl,
Rectangle bounds, Point lp, DataLabelOverlapMode ovlMode, DataLabelVisualStyle dstyle)
{
if ((dstyle.CenterLabel != Tbool.True) ||
SetLabelCenter(series, pl, bounds, ovlMode, dstyle) == false)
{
ConnectorLineVisualStyle cstyle = dstyle.ConnectorLineStyle;
int step;
int startAngle = GetStartAngle(lp, pl, cstyle, out step);
int offset = 0;
if (cstyle.Origin == ConnectorOrigin.Edge)
{
offset = Math.Max(
pl.SeriesPoint.PointSize.Width,
pl.SeriesPoint.PointSize.Height) / 2;
}
SetLabel(series, pl, startAngle, step,
cstyle.MinLength + offset, cstyle.MaxLength + offset, ovlMode, bounds, dstyle);
}
}
#endregion
#region GetBoundsSize
private Size GetBoundsSize(
ChartSeries series, PointLabel pl, DataLabelVisualStyle dstyle)
{
RotateDegrees rotate = series.GetRotateDegrees(dstyle);
Size size = (rotate == RotateDegrees.Rotate90 || rotate == RotateDegrees.Rotate270)
? new Size(pl.LabelSize.Height, pl.LabelSize.Width) : pl.LabelSize;
if (dstyle.HasBorder == true)
{
size.Width += (dstyle.BorderThickness << 1);
size.Height += (dstyle.BorderThickness << 1);
}
size.Width += dstyle.Padding.Horizontal;
size.Height += dstyle.Padding.Vertical;
return (size);
}
#endregion
#region SetLabelCenter
private bool SetLabelCenter(ChartSeries series, PointLabel pl,
Rectangle bounds, DataLabelOverlapMode ovlMode, DataLabelVisualStyle dstyle)
{
Rectangle t = GetCenteredRectangle(series, pl.Point, pl.LabelSize);
if (IsFreeArea(t, bounds, ovlMode, true, true) == true)
{
pl.Bounds = t;
pl.EdgePoint = new Point(t.Right, t.Bottom);
return (true);
}
if (ovlMode == DataLabelOverlapMode.HideOverlapping)
return (true);
return (false);
}
#endregion
#region SetLabel
private bool SetLabel(ChartSeries series, PointLabel pl, int startAngle, int step,
int radius, int maxRadius, DataLabelOverlapMode ovlMode, Rectangle bounds, DataLabelVisualStyle dstyle)
{
int angle = startAngle;
int pass = 0;
radius = Dpi.Width(radius);
maxRadius = Dpi.Width(maxRadius);
while (radius <= maxRadius)
{
Point calcPoint;
Rectangle r = GetAreaRectangle(series, pl, angle, radius, out calcPoint, dstyle);
if (IsFreeArea(r, bounds, ovlMode, true, true) == true)
{
pl.Angle = angle;
pl.Bounds = r;
pl.EdgePoint = calcPoint;
return (true);
}
if (ovlMode != DataLabelOverlapMode.RotateAroundPoint)
break;
int pval = pass / 2 + 1;
if (pass % 2 > 0)
pval = -pval;
angle = (startAngle + (pval * step)) % 360;
pass++;
if (pass * step >= 360)
{
radius += Dpi.Width15;
pass = 0;
}
}
pl.Bounds = Rectangle.Empty;
pl.EdgePoint = Point.Empty;
return (false);
}
#endregion
#region GetStartAngle
private int GetStartAngle(Point lp,
PointLabel pl, ConnectorLineVisualStyle cstyle, out int step)
{
step = cstyle.AngleStep;
if (cstyle.DefaultAngle >= 0)
return (cstyle.DefaultAngle);
Point pt = pl.Point;
int rise = lp.Y - pt.Y;
int run = lp.X - pt.X;
double slope = (run == 0) ? 0 : (double)rise / run;
return ((slope < 1) ? 270 : (slope > 0) ? 315 : 225);
}
#endregion
#region GetCenteredRectangle
private Rectangle GetCenteredRectangle(
ChartSeries series, Point pt, Size labelSize)
{
Rectangle r = new Rectangle(pt, labelSize);
r.X -= (r.Width / 2);
r.Y -= (r.Height / 2);
return (r);
}
#endregion
#region GetAreaRectangle
private Rectangle GetAreaRectangle(ChartSeries series, PointLabel pl,
int angle, int radius, out Point calcPoint, DataLabelVisualStyle dstyle)
{
Rectangle r = new Rectangle(pl.Point, pl.LabelSize);
RotateDegrees rotate = series.GetRotateDegrees(dstyle);
if (rotate == RotateDegrees.Rotate90 || rotate == RotateDegrees.Rotate270)
{
r.Width = pl.LabelSize.Height;
r.Height = pl.LabelSize.Width;
}
if (dstyle.HasBorder == true)
{
int n = Dpi.Width(dstyle.BorderThickness) << 1;
r.Width += n;
r.Height += n;
}
r.Width += Dpi.Width(dstyle.Padding.Horizontal);
r.Height += Dpi.Height(dstyle.Padding.Vertical);
r.X += (int)(radius * Math.Cos(MathHelper.ToRadians(angle)));
r.Y += (int)(radius * Math.Sin(MathHelper.ToRadians(angle)));
calcPoint = r.Location;
return (OffsetAreaRectangle(r, angle, ref calcPoint, dstyle));
}
#region OffsetAreaRectangle
private Rectangle OffsetAreaRectangle(Rectangle r,
int angle, ref Point calcPoint, DataLabelVisualStyle dstyle)
{
if (angle == 0)
{
r.Y -= (r.Height / 2);
}
else if (angle == 90)
{
r.X -= (r.Width / 2);
}
else if (angle == 180)
{
r.X -= r.Width;
r.Y -= (r.Height / 2);
}
else if (angle == 270)
{
r.X -= (r.Width / 2);
r.Y -= r.Height;
}
else if (angle < 90)
{
}
else if (angle < 180)
{
r.X -= r.Width;
}
else if (angle < 270)
{
r.X -= r.Width;
r.Y -= r.Height;
}
else
{
r.Y -= r.Height;
}
return (r);
}
#endregion
#endregion
#region IsFreeArea
private bool IsFreeArea(
Rectangle r, Rectangle bounds, DataLabelOverlapMode ovlMode, bool xos, bool yos)
{
if (xos == true)
{
if (r.X < bounds.X || r.Right > bounds.Right)
return (false);
}
if (yos == true)
{
if (r.Y < bounds.Y || r.Bottom > bounds.Bottom)
return (false);
}
if (ovlMode == DataLabelOverlapMode.ShowOverlapping)
return (true);
r.Inflate(3, 3);
for (int i = 0; i < _LabelGroups.Count; i++)
{
List<PointLabel> lps = _LabelGroups[i].PointLabels;
for (int j = 0; j < lps.Count; j++)
{
PointLabel pl = lps[j];
if (pl.Bounds.IsEmpty == false)
{
if (pl.Bounds.IntersectsWith(r) == true)
return (false);
}
}
}
return (true);
}
#endregion
#endregion
}
}

View File

@@ -0,0 +1,351 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using DevComponents.DotNetBar.Charts.Style;
namespace DevComponents.DotNetBar.Charts
{
/// <summary>
/// Represents a PointLabel group.
/// </summary>
public class PointLabelGroup
{
#region Private data
private ChartSeries _ChartSeries;
private List<PointLabel> _PointLabels;
#endregion
public PointLabelGroup(ChartSeries chartSeries, List<PointLabel> pointLabels)
{
_ChartSeries = chartSeries;
_PointLabels = pointLabels;
}
#region Public properties
#region ChartSeries
/// <summary>
/// Gets or sets the associated chart series.
/// </summary>
public ChartSeries ChartSeries
{
get { return (_ChartSeries); }
set { _ChartSeries = value; }
}
#endregion
#region PointLabels
/// <summary>
/// Gets or sets the associated list of PointLabels.
/// </summary>
public List<PointLabel> PointLabels
{
get { return (_PointLabels); }
set { _PointLabels = value; }
}
#endregion
#endregion
}
/// <summary>
/// Represents a PointLabel (label associated with a data point in the chart).
/// </summary>
public class PointLabel : IDisposable
{
#region Private data
private SeriesPoint _SeriesPoint;
private float _Angle;
private Rectangle _Bounds;
private Point _EdgePoint;
private Point _Point;
private string _Label;
private Size _LabelSize;
private BarLabelPosition _BarLabelPosition = BarLabelPosition.NotSet;
private DataLabelVisualStyle _DataLabelVisualStyle;
private States _States;
#endregion
public PointLabel(SeriesPoint sp, Point pt, string label)
{
_SeriesPoint = sp;
_Point = pt;
_Label = label;
InitDefaultStates();
}
#region InitDefaultStates
private void InitDefaultStates()
{
SetState(States.Visible, true);
SetState(States.NeedsMeasured, true);
}
#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 BarLabelPosition
/// <summary>
/// Gets or sets the position of bar series labels.
/// </summary>
[Description("Indicates the position of bar series labels.")]
public BarLabelPosition BarLabelPosition
{
get { return (_BarLabelPosition); }
set { _BarLabelPosition = value; }
}
#endregion
#region DataLabelVisualStyle
/// <summary>
/// Gets or sets the visual style for the data label.
/// </summary>
public DataLabelVisualStyle DataLabelVisualStyle
{
get { return (_DataLabelVisualStyle); }
set
{
if (value != _DataLabelVisualStyle)
{
DataLabelVisualStyle oldValue = _DataLabelVisualStyle;
_DataLabelVisualStyle = value;
StyleVisualChangeHandler(oldValue, value);
}
}
}
#endregion
#region FixedSize
/// <summary>
/// Gets or set whether the LabelSize is a fixed size.
/// </summary>
public bool IsFixedSize
{
get { return (TestState(States.IsFixedSize)); }
set { SetState(States.IsFixedSize, value); }
}
#endregion
#region Label
/// <summary>
/// Gets or sets the label text
/// </summary>
public string Label
{
get { return (_Label); }
set
{
NeedsMeasured = true;
_Label = value;
}
}
#endregion
#region LabelSize
/// <summary>
/// Gets or sets the label size.
/// </summary>
public Size LabelSize
{
get { return (_LabelSize); }
set
{
_LabelSize = value;
NeedsMeasured = false;
}
}
#endregion
#region SeriesPoint
/// <summary>
/// Gets the associated SeriesPoint.
/// </summary>
public SeriesPoint SeriesPoint
{
get { return (_SeriesPoint); }
internal set { _SeriesPoint = value; }
}
#endregion
#region Visible
/// <summary>
/// Gets or sets whether the label is visible.
/// </summary>
public bool Visible
{
get { return (TestState(States.Visible)); }
set { SetState(States.Visible, value); }
}
#endregion
#endregion
#region Internal properties
#region Bounds
internal Rectangle Bounds
{
get { return (_Bounds); }
set { _Bounds = value; }
}
#endregion
#region EdgePoint
internal Point EdgePoint
{
get { return (_EdgePoint); }
set { _EdgePoint = value; }
}
#endregion
#region IsDataLabel
internal bool IsDataLabel
{
get { return (TestState(States.IsDataLabel)); }
set { SetState(States.IsDataLabel, value); }
}
#endregion
#region NeedsMeasured
internal bool NeedsMeasured
{
get { return (TestState(States.NeedsMeasured)); }
set { SetState(States.NeedsMeasured, value); }
}
#endregion
#region Point
internal Point Point
{
get { return (_Point); }
set { _Point = value; }
}
#endregion
#endregion
#region States
[Flags]
private enum States : uint
{
IsFixedSize = (1U << 0),
NeedsMeasured = (1U << 1),
Visible = (1U << 2),
IsDataLabel = (1U << 3),
}
#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 StyleVisualChangeHandler
private void StyleVisualChangeHandler(
INotifyPropertyChanged oldValue, INotifyPropertyChanged newValue)
{
if (oldValue != null)
oldValue.PropertyChanged -= StyleChanged;
if (newValue != null)
newValue.PropertyChanged += StyleChanged;
}
private void StyleChanged(object sender, PropertyChangedEventArgs e)
{
NeedsMeasured = true;
}
#endregion
#region IDisposable
public void Dispose()
{
DataLabelVisualStyle = null;
}
#endregion
}
}

View File

@@ -0,0 +1,565 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using DevComponents.DotNetBar.Charts.Style;
namespace DevComponents.DotNetBar.Charts
{
internal class PointMarker : IDisposable
{
#region Private variables
private List<BitmapEntry> _Bitmaps = new List<BitmapEntry>();
#endregion
#region GetMarkerBitmap
public Bitmap GetMarkerBitmap(Graphics g, PointMarkerType markerType, int markerPoints,
Size size, int markerRotation, Background background, Color borderColor, int borderWidth)
{
if (markerType == PointMarkerType.None || markerType == PointMarkerType.NotSet)
return (null);
if (markerType == PointMarkerType.Cross ||
background == null || background.IsEmpty)
{
if (borderColor.IsEmpty)
borderColor = Color.Black;
}
// Add margin to permit better antialiasing of image
size.Width++;
size.Height++;
Bitmap bitmap = null;
bitmap = FindBitmap(markerType, markerPoints,
size, markerRotation, background, borderColor, borderWidth);
if (bitmap == null)
{
size.Width = Math.Max(size.Width, 3);
size.Height = Math.Max(size.Height, 3);
Rectangle r = new Rectangle(Point.Empty, size);
using (GraphicsPath path =
GetMarkerPath(markerType, markerPoints, markerRotation, r, borderWidth))
{
if (path != null)
{
bitmap = new Bitmap(size.Width, size.Height, g);
using (Graphics gBmp = Graphics.FromImage(bitmap))
{
gBmp.SmoothingMode = SmoothingMode.AntiAlias;
FillMarkerPath(gBmp, path, r, markerType, background, borderColor, borderWidth);
if (markerRotation != 0 && markerRotation != -1)
{
Bitmap bitmap2 = RotatePic(bitmap, markerRotation);
bitmap.Dispose();
bitmap = bitmap2;
}
_Bitmaps.Add(new BitmapEntry(markerType, size, markerPoints,
markerRotation, background, borderColor, borderWidth, bitmap));
}
}
}
}
return (bitmap);
}
#endregion
#region FindBitmap
public Bitmap FindBitmap(PointMarkerType markerType, int markerPoints,
Size size, int markerRotation, Background background, Color borderColor, int borderWidth)
{
foreach (BitmapEntry entry in _Bitmaps)
{
if (entry.MarkerType == markerType &&
entry.MarkerPoints == markerPoints &&
entry.MarkerRotation == markerRotation &&
entry.MarkerSize.Equals(size) &&
entry.BorderWidth == borderWidth &&
entry.BorderColor.Equals(borderColor) &&
entry.Background.IsEqualTo(background))
{
return (entry.Bitmap);
}
}
return (null);
}
#endregion
#region GetMarkerPath
internal GraphicsPath GetMarkerPath( PointMarkerType markerType,
int markerPoints, int markerRotation, Rectangle r, int borderWidth)
{
r.Inflate(-borderWidth, -borderWidth);
if (r.Width > 0 && r.Height > 0)
{
switch (markerType)
{
case PointMarkerType.Ellipse:
return (GetCirclePath(r));
case PointMarkerType.Cross:
return (GetCrossPath(r, markerPoints));
case PointMarkerType.Diamond:
return (GetDiamondPath(r));
case PointMarkerType.Rectangle:
return (GetRectanglePath(r));
case PointMarkerType.Star:
return (GetStarPath(r, markerPoints));
case PointMarkerType.Triangle:
return (GetTrianglePath(r));
default:
return (GetPolygonPath(r, markerPoints));
}
}
return (null);
}
#region GetCirclePath
private GraphicsPath GetCirclePath(Rectangle r)
{
GraphicsPath path = new GraphicsPath();
path.AddEllipse(r);
return (path);
}
#endregion
#region GetCrossPath
private GraphicsPath GetCrossPath(Rectangle r, int points)
{
GraphicsPath path = new GraphicsPath();
PointF[] pts = new PointF[2 * points];
double rx1 = r.Width / 2;
double ry1 = r.Height / 2;
if (rx1 < 2)
rx1 = 2;
if (ry1 < 2)
ry1 = 2;
double cx = r.X + rx1;
double cy = r.Y + ry1;
double theta = MathHelper.ToRadians(270);
double dtheta = Math.PI / points;
for (int i = 0; i < 2 * points; i += 2)
{
pts[i] = new PointF(
(float)(cx + rx1 * Math.Cos(theta)),
(float)(cy + ry1 * Math.Sin(theta)));
pts[i + 1] = new PointF((float)cx, (float)cy);
theta += (dtheta * 2);
}
path.AddPolygon(pts);
path.CloseAllFigures();
return (path);
}
#endregion
#region GetDiamondPath
private GraphicsPath GetDiamondPath(Rectangle r)
{
GraphicsPath path = new GraphicsPath();
int dx = r.Width / 2;
int dy = r.Height / 2;
int mx = r.X + dx;
int my = r.Y + dy;
Point[] pts =
{
new Point(mx, my - dy),
new Point(mx + dx, my),
new Point(mx, my + dy),
new Point(mx - dx, my),
};
path.AddPolygon(pts);
path.CloseAllFigures();
return (path);
}
#endregion
#region GetPolygonPath
private GraphicsPath GetPolygonPath(Rectangle r, int sides)
{
if (sides <= 4)
return (GetRectanglePath(r));
GraphicsPath path = new GraphicsPath();
int radius = Math.Min(r.Width, r.Height);
float dx = (float)radius / 2;
float radians = (float)MathHelper.ToRadians(270);
float delta = (float)MathHelper.ToRadians((float)360 / sides);
Point[] pts = new Point[sides];
for (int i = 0; i < sides; i++)
{
pts[i] = new Point(
(int)(dx * Math.Cos(radians) + dx + r.X),
(int)(dx * Math.Sin(radians) + dx + r.Y));
radians += delta;
}
path.AddPolygon(pts);
path.CloseAllFigures();
if (r.Width != r.Height)
{
PointF[] dp =
{
new PointF(0, 0),
new PointF(r.Width, 0),
new PointF(0, r.Height),
};
path.Warp(dp, new RectangleF(0, 0, radius, radius));
}
return (path);
}
#endregion
#region GetRectanglePath
private GraphicsPath GetRectanglePath(Rectangle r)
{
GraphicsPath path = new GraphicsPath();
path.AddRectangle(r);
return (path);
}
#endregion
#region GetStarPath
private GraphicsPath GetStarPath(Rectangle r, int points)
{
if (points < 2)
points = 2;
GraphicsPath path = new GraphicsPath();
PointF[] pts = new PointF[2 * points];
double rx1 = r.Width / 2;
double ry1 = r.Height / 2;
if (rx1 < 2)
rx1 = 2;
if (ry1 < 2)
ry1 = 2;
double rx2 = rx1 / 2;
double ry2 = ry1 / 2;
double cx = r.X + rx1;
double cy = r.Y + ry1;
double theta = MathHelper.ToRadians(270);
double dtheta = Math.PI / points;
for (int i = 0; i < 2 * points; i += 2)
{
pts[i] = new PointF(
(float)(cx + rx1 * Math.Cos(theta)),
(float)(cy + ry1 * Math.Sin(theta)));
theta += dtheta;
pts[i + 1] = new PointF(
(float)(cx + rx2 * Math.Cos(theta)),
(float)(cy + ry2 * Math.Sin(theta)));
theta += dtheta;
}
path.AddPolygon(pts);
path.CloseAllFigures();
return (path);
}
#endregion
#region GetTrianglePath
private GraphicsPath GetTrianglePath(Rectangle r)
{
// Equal height and width will not be adjusted to make
// an equalaterial triangle - thus rotation will skew image.
GraphicsPath path = new GraphicsPath();
int dx = r.Width / 2;
int dy = r.Height / 2;
Point[] pts = {
new Point(r.X + dx, r.Y),
new Point(r.X , r.Y + dy * 2),
new Point(r.X + dx * 2, r.Y + dy * 2),
};
path.AddPolygon(pts);
path.CloseAllFigures();
return (path);
}
#endregion
#endregion
#region FillMarkerPath
internal void FillMarkerPath(Graphics g, GraphicsPath path, Rectangle r,
PointMarkerType markerType, Background background, Color borderColor, int borderWidth)
{
if (markerType != PointMarkerType.Cross)
{
BackFillType fillType = GetMarkerFillType(markerType, background);
using (Brush br = background.GetBrush(r, -1, fillType))
g.FillPath(br, path);
}
if (borderColor.IsEmpty == false && borderWidth > 0)
{
using (Pen pen = new Pen(borderColor, borderWidth))
g.DrawPath(pen, path);
}
}
#region GetMarkerFillType
private BackFillType GetMarkerFillType(PointMarkerType markerType, Background background)
{
if (background.Color2.IsEmpty == true)
return (BackFillType.None);
if (background.BackFillType == BackFillType.Auto)
{
switch (markerType)
{
case PointMarkerType.Ellipse:
case PointMarkerType.Star:
return (BackFillType.Center);
default:
return (BackFillType.VerticalCenter);
}
}
return (background.BackFillType);
}
#endregion
#endregion
#region RotatePic
private Bitmap RotatePic(Bitmap obmp, float angle)
{
float rad = (float)MathHelper.ToRadians(angle);
double fW = Math.Abs((Math.Cos(rad) * obmp.Width)) + Math.Abs((Math.Sin(rad) * obmp.Height));
double fH = Math.Abs((Math.Sin(rad) * obmp.Width)) + Math.Abs((Math.Cos(rad) * obmp.Height));
Bitmap nbmp = new Bitmap((int)Math.Ceiling(fW), (int)Math.Ceiling(fH));
using (Graphics g = Graphics.FromImage(nbmp))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
float hw = nbmp.Width / 2f;
float hh = nbmp.Height / 2f;
Matrix m = g.Transform;
m.RotateAt(angle, new PointF(hw, hh), MatrixOrder.Append);
g.Transform = m;
g.DrawImage(obmp, new PointF((float)((nbmp.Width - obmp.Width) / 2), (float)((nbmp.Height - obmp.Height) / 2)));
}
return nbmp;
}
#endregion
#region Clear
public void Clear()
{
foreach (BitmapEntry entry in _Bitmaps)
{
entry.Background.Dispose();
entry.Bitmap.Dispose();
}
_Bitmaps.Clear();
}
#endregion
#region IDisposable Members
public void Dispose()
{
Clear();
}
#endregion
#region BitmapEntry
private class BitmapEntry
{
public PointMarkerType MarkerType;
public Size MarkerSize;
public int MarkerPoints;
public int MarkerRotation;
public Background Background;
public Color BorderColor;
public int BorderWidth;
public Bitmap Bitmap;
public BitmapEntry(PointMarkerType markerType, Size markerSize, int markerPoints,
int markerRotation, Background background, Color borderColor, int borderWidth, Bitmap bitmap)
{
MarkerType = markerType;
MarkerSize = markerSize;
MarkerPoints = markerPoints;
MarkerRotation = markerRotation;
Background = background.Copy();
BorderColor = borderColor;
BorderWidth = borderWidth;
Bitmap = bitmap;
}
}
#endregion
}
#region enums
#region PointMarkerType
public enum PointMarkerType
{
/// <summary>
/// Type not set.
/// </summary>
NotSet = -1,
/// <summary>
/// No Marker
/// </summary>
None,
/// <summary>
/// Cross
/// </summary>
Cross,
/// <summary>
/// Diamond
/// </summary>
Diamond,
/// <summary>
/// Ellipse
/// </summary>
Ellipse,
/// <summary>
/// Polygon (Pentagon, Hexagon, etc)
/// </summary>
Polygon,
/// <summary>
/// Rectangle
/// </summary>
Rectangle,
/// <summary>
/// Star
/// </summary>
Star,
/// <summary>
/// Triangle
/// </summary>
Triangle,
}
#endregion
#endregion
}