5492 lines
158 KiB
C#

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.DotNetBar.Charts.Style;
namespace DevComponents.DotNetBar.Charts
{
/// <summary>
/// Represents the collection of Chart AxesX.
/// </summary>
[Editor("DevComponents.Charts.Design.ChartAxesCollectionEditor, DevComponents.Charts.Design, " +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public class ChartAxesXCollection : ChartAxesCollection
{
public ChartAxesXCollection()
: base(AxisOrientation.X)
{
}
#region GetUniqueName
public string GetUniqueName()
{
return (GetUniqueName("AncAxisX"));
}
#endregion
}
/// <summary>
/// Represents the collection of Chart AxesY.
/// </summary>
[Editor("DevComponents.Charts.Design.ChartAxesCollectionEditor, DevComponents.Charts.Design, " +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public class ChartAxesYCollection : ChartAxesCollection
{
public ChartAxesYCollection()
: base(AxisOrientation.Y)
{
}
#region GetUniqueName
public string GetUniqueName()
{
return (GetUniqueName("AncAxisY"));
}
#endregion
}
/// <summary>
/// Represents the collection of Chart Axes.
/// </summary>
public class ChartAxesCollection : CustomNamedCollection<ChartAxis>
{
#region Private variables
private AxisOrientation _AxisOrientation;
#endregion
public ChartAxesCollection(AxisOrientation axisOrientation)
{
_AxisOrientation = axisOrientation;
}
#region Public properties
#region AxisOrientation
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public AxisOrientation AxisOrientation
{
get { return (_AxisOrientation); }
}
#endregion
#endregion
#region InsertItem
protected override void InsertItem(int index, ChartAxis item)
{
if (item.IsPrimaryAxis == true)
throw new Exception("Primary Axes cannot be added as Ancillary Axes.");
base.InsertItem(index, item);
}
#endregion
}
#region ChartAxisX
/// <summary>
/// Represents an X-Axis element.
/// </summary>
[TypeConverter(typeof(BlankExpandableObjectConverter))]
public class ChartAxisX : ChartAxis
{
#region Constructors
public ChartAxisX()
: base(AxisOrientation.X)
{
}
public ChartAxisX(string name)
: base(AxisOrientation.X)
{
Name = name;
}
public ChartAxisX(string name, object minValue, object maxValue)
: base(AxisOrientation.X)
{
Name = name;
MinValue = minValue;
MaxValue = MaxValue;
}
#endregion
#region Public properties
#region MajorGridLines
///<summary>
/// Gets the axis MajorGridLines element.
///</summary>
[Description("Indicates the MajorGridLines element.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public override ChartMajorGridLines MajorGridLines
{
get
{
if (_MajorGridLines == null)
{
_MajorGridLines = new ChartMajorGridLinesX();
_MajorGridLines.Parent = this;
}
return (_MajorGridLines);
}
}
#endregion
#region MajorTickmarks
///<summary>
/// Gets the axis MajorTickmarks element.
///</summary>
[Description("Indicates the MajorTickmarks element.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public override MajorTickmarks MajorTickmarks
{
get
{
if (_MajorTickmarks == null)
{
_MajorTickmarks = new MajorTickmarksX();
_MajorTickmarks.Parent = this;
}
return (_MajorTickmarks);
}
}
#endregion
#region MinorGridLines
///<summary>
/// Gets the axis MinorGridLines element.
///</summary>
[Description("Indicates the MinorGridLines element.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public override ChartMinorGridLines MinorGridLines
{
get
{
if (_MinorGridLines == null)
{
_MinorGridLines = new ChartMinorGridLinesX();
_MinorGridLines.Parent = this;
}
return (_MinorGridLines);
}
}
#endregion
#region MinorTickmarks
///<summary>
/// Gets the axis MinorTickmarks element.
///</summary>
[Description("Indicates the MinorTickmarks element.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public override MinorTickmarks MinorTickmarks
{
get
{
if (_MinorTickmarks == null)
{
_MinorTickmarks = new MinorTickmarksX();
_MinorTickmarks.Parent = this;
}
return (_MinorTickmarks);
}
}
#endregion
#endregion
#region MeasureOverride
protected override void MeasureOverride(ChartLayoutInfo layoutInfo)
{
ChartXy chartXy = Parent as ChartXy;
ChartAxisVisualStyle astyle = EffectiveAxisStyle;
AxisAlignment axisAlignment = GetAxisAlignment();
Rectangle bounds = layoutInfo.LayoutBounds;
if (Visible == true)
{
MeasureTitle(layoutInfo, axisAlignment);
int width = Math.Max(layoutInfo.LayoutBounds.Width, Dpi.Width(chartXy.MinContentSize.Width));
int tickmarkLen = MeasureTickmarks(layoutInfo, width);
bounds.Height = GetMeasuredHeight();
layoutInfo.LayoutBounds.Height -= tickmarkLen;
if (axisAlignment == AxisAlignment.Far)
{
layoutInfo.LayoutBounds.Y += tickmarkLen;
}
else
{
bounds.Y = layoutInfo.LayoutBounds.Bottom;
if (EdgeAxis == true)
{
bounds.Y--;
if (chartXy.DropShadowDisplayed == true)
layoutInfo.LayoutBounds.Height += 3;
}
}
}
else
{
int width = Math.Max(layoutInfo.LayoutBounds.Width, Dpi.Width(chartXy.MinContentSize.Width));
MeasureTickmarks(layoutInfo, width);
bounds.Height = 0;
}
CalcAxisBounds(layoutInfo, axisAlignment, bounds);
BoundsRelative = bounds;
base.MeasureOverride(layoutInfo);
}
#region MeasureTitle
protected void MeasureTitle(
ChartLayoutInfo layoutInfo, AxisAlignment axisAlignment)
{
if (Title.Visible == true)
{
Title.XyAlignment = (axisAlignment == AxisAlignment.Near)
? XyAlignment.Bottom : XyAlignment.Top;
Title.Measure(layoutInfo);
}
}
#endregion
#region MeasureTickmarks
protected virtual int MeasureTickmarks(ChartLayoutInfo layoutInfo, int width)
{
CalcMajorSpacing(layoutInfo, width);
MajorTickmarks.TickmarkLayout = TickmarkLayout;
MinorTickmarks.TickmarkLayout = TickmarkLayout;
MajorTickmarks.Measure(layoutInfo);
MinorTickmarks.Measure(layoutInfo);
return (Math.Max(MajorTickmarks.Size.Height,
MinorTickmarks.Size.Height));
}
#endregion
#region GetMeasuredHeight
private int GetMeasuredHeight()
{
int height = Math.Max(MajorTickmarks.Size.Height,
MinorTickmarks.Size.Height);
if (Title.Visible == true)
height += Title.Size.Height;
return (height);
}
#endregion
#region CalcAxisBounds
private void CalcAxisBounds(ChartLayoutInfo layoutInfo,
AxisAlignment axisAlignment, Rectangle bounds)
{
ChartXy chartXy = Parent as ChartXy;
int labelHeight = 0;
int tmInnerLength = 0;
int tmOuterLength = 0;
if (TickmarkLayout.MajorCount > 0)
{
labelHeight = MajorTickmarks.GetTotalLabelHeight();
tmOuterLength = Dpi.Width(GetMaxTickMarkLength(false));
tmInnerLength = Dpi.Width(GetMaxTickMarkLength(true));
if (axisAlignment == AxisAlignment.Near)
{
if (EdgeAxis == true)
{
if (chartXy.HScrollBar.Visible == true)
tmInnerLength += (chartXy.HScrollBar.Height + 1);
bounds.Y -= tmInnerLength;
}
}
else
{
if (Title.Visible == true)
bounds.Y += Title.Size.Height;
}
bounds.Height = (labelHeight + tmOuterLength + tmInnerLength + 1);
AxisBounds = bounds;
Rectangle r = bounds;
r.Height = 1;
if (axisAlignment == AxisAlignment.Near)
{
r.Y += tmInnerLength;
if (EdgeAxis == false)
r.Y += 1;
}
else
{
r.Y = bounds.Bottom - tmInnerLength - 1;
}
AxisLineBounds = r;
}
}
#endregion
#endregion
#region ArrangeOverride
protected override void ArrangeOverride(ChartLayoutInfo layoutInfo)
{
ChartXy chartXy = Parent as ChartXy;
// Let the axis bounds extend into the chart's frame
// area as much as possible for better label display.
Rectangle r = AxisBounds;
r.Width = chartXy.ContentBounds.Width;
int n1 = r.X - chartXy.FrameBounds.X;
int n2 = chartXy.FrameBounds.Right - r.Right;
r.X = chartXy.FrameBounds.X;
r.Width += (n1 + n2);
AxisBounds = r;
r = AxisLineBounds;
r.Width = chartXy.ContentBounds.Width;
AxisLineBounds = r;
base.ArrangeOverride(layoutInfo);
}
#endregion
#region RenderOverride
protected override void RenderOverride(ChartRenderInfo renderInfo)
{
if (Visible == true)
{
base.RenderOverride(renderInfo);
Graphics g = renderInfo.Graphics;
ChartAxisVisualStyle astyle = EffectiveAxisStyle;
if (TickmarkLayout.MajorCount > 0)
{
Rectangle axisBounds = GetScrollBounds(AxisBounds);
Region clip = g.Clip;
g.SetClip(axisBounds, CombineMode.Intersect);
MajorTickmarks.Render(renderInfo);
MinorTickmarks.Render(renderInfo);
RenderAxisLine(g, astyle);
g.Clip = clip;
}
}
}
#region RenderAxisLine
private void RenderAxisLine(Graphics g, ChartAxisVisualStyle astyle)
{
if (astyle.AxisColor.IsEmpty == false &&
astyle.AxisColor.Equals(Color.Transparent) == false)
{
Rectangle alBounds = GetScrollBounds(AxisLineBounds);
using (Pen pen = new Pen(astyle.AxisColor, Dpi.Height1))
g.DrawLine(pen, alBounds.X, alBounds.Y, alBounds.Right - 1, alBounds.Y);
}
}
#endregion
#endregion
#region RenderCrosshairLabel (Point)
internal override void RenderCrosshairLabel(Graphics g, Point pt)
{
TickmarkLayout layout = TickmarkLayout;
if (layout != null && layout.Ticks != null && layout.Ticks.Length > 0)
{
TickmarkTick tick = layout.Ticks[0];
CrosshairValueVisualStyle lstyle = EffectiveCrosshairLabelStyle;
string text = GetCrosshairLabel(pt, layout, tick, lstyle);
if (string.IsNullOrEmpty(text) == false)
{
Rectangle r = GetCrosshairBounds(g, text, pt, lstyle);
lstyle.RenderBackground(g, r);
lstyle.RenderBorder(g, r);
if (lstyle.DropShadow.Enabled == Tbool.True)
lstyle.DropShadow.RenderDropShadow(g, r, true, true);
using (StringFormat sf = new StringFormat())
{
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
using (Brush br = new SolidBrush(lstyle.TextColor))
g.DrawString(text, lstyle.Font, br, r, sf);
}
}
}
}
#region GetCrosshairLabel
private string GetCrosshairLabel(Point pt,
TickmarkLayout layout, TickmarkTick tick, CrosshairValueVisualStyle lstyle)
{
object value = null;
switch (ScaleType)
{
case ScaleType.DateTime:
value = GetValueFromPoint(layout, pt);
break;
case ScaleType.Qualitative:
pt = GetChartPoint(pt);
int n = (int)Math.Floor((pt.X - (layout.NearMargin + layout.MarginOffset -
layout.MajorInterval / 2 + tick.TickPoint.X)) / (layout.MajorInterval * layout.MajorSpacing));
n += tick.Index;
if ((uint)n < QualitativeValues.Count)
value = QualitativeValues[n];
break;
case ScaleType.Quantitative:
double dvalue = Convert.ToDouble(GetValueFromPoint(layout, pt));
if (DotPlotAxis == true && Math.Floor(layout.MajorSpacing) == layout.MajorSpacing)
dvalue = Math.Floor(dvalue + .5);
value = dvalue;
break;
}
return (GetCrosshairLabel(value, lstyle));
}
#endregion
#region GetCrosshairBounds
private Rectangle GetCrosshairBounds(Graphics g,
string text, Point pt, CrosshairValueVisualStyle lstyle)
{
Rectangle bounds = GetScrollBounds(MajorTickmarks.LabelBounds);
Rectangle r = bounds;
SizeF sizef = g.MeasureString(text, lstyle.Font);
r.Width = (int)(sizef.Width + 2);
r.Height = (int)(sizef.Height + 2);
r.X = pt.X - (int)(sizef.Width / 2);
r.Y--;
AxisAlignment axisalignment = GetAxisAlignment();
if (lstyle.Margin.IsEmpty == false)
{
if (axisalignment == AxisAlignment.Near)
r.Y += lstyle.Margin.Top;
else
r.Y -= lstyle.Margin.Bottom;
}
if (axisalignment == AxisAlignment.Near)
r.Y += (lstyle.BorderThickness.Vertical);
else
r.Y -= (lstyle.BorderThickness.Vertical);
r.Height += lstyle.BorderThickness.Vertical;
if (lstyle.Padding.IsEmpty == false)
{
if (axisalignment == AxisAlignment.Far)
r.Y -= lstyle.Padding.Vertical;
r.Height += lstyle.Padding.Vertical;
r.X -= lstyle.Padding.Left;
r.Width += lstyle.Padding.Horizontal;
}
if (r.Bottom > bounds.Bottom)
r.Y -= (r.Bottom - bounds.Bottom);
if (r.Right > bounds.Right)
r.X -= (r.Right - bounds.Right);
return (r);
}
#endregion
#endregion
#region RenderCrosshairLabel (CrosshairPoint)
internal override void RenderCrosshairLabel(Graphics g, CrosshairPoint cp)
{
CrosshairValueVisualStyle lstyle = EffectiveCrosshairLabelStyle;
string text = (cp.ChartSeries.IsRotated == false)
? GetCrosshairLabel(cp.SeriesPoint.ValueX, lstyle)
: GetCrosshairLabel(cp.SeriesPoint.ValueY[cp.ValueIndex], lstyle);
if (string.IsNullOrEmpty(text) == false)
{
Rectangle r = GetCrosshairBounds(g, text, cp.Point, lstyle);
lstyle.RenderBackground(g, r);
lstyle.RenderBorder(g, r);
if (lstyle.DropShadow.Enabled == Tbool.True)
lstyle.DropShadow.RenderDropShadow(g, r, true, true);
using (StringFormat sf = new StringFormat())
{
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
using (Brush br = new SolidBrush(lstyle.TextColor))
g.DrawString(text, lstyle.Font, br, r, sf);
}
}
}
#endregion
#region RenderBackground
internal override void RenderBackground(ChartRenderInfo renderInfo, Rectangle scContentBounds)
{
if (UseAlternateBackground == true)
{
if (TickmarkLayout.Ticks != null)
{
Graphics g = renderInfo.Graphics;
ChartXy chartXy = Parent as ChartXy;
Point pt = chartXy.GetLocalAdjustedPoint(Point.Empty);
if (ScaleType == ScaleType.Qualitative)
pt.X -= (int)(TickmarkLayout.MajorInterval / 2);
ChartAxisVisualStyle astyle = EffectiveAxisStyle;
if (astyle.AlternateBackground.IsSolidBrush == true)
{
using (Brush br = astyle.AlternateBackground.GetBrush(Rectangle.Empty))
{
RenderAltBackground(g,
scContentBounds, pt, TickmarkLayout, astyle, br);
}
}
else
{
RenderAltBackground(g,
scContentBounds, pt, TickmarkLayout, astyle, null);
}
}
}
}
#region RenderAltBackground
private void RenderAltBackground(Graphics g, Rectangle scContentBounds,
Point pt, TickmarkLayout TickmarkLayout, ChartAxisVisualStyle astyle, Brush br)
{
foreach (TickmarkTick tmi in TickmarkLayout.Ticks)
{
double value = GetTickmarkAltValue(tmi);
int n = (int)(Math.Ceiling(value / TickmarkLayout.MajorSpacing));
if (n % 2 == 0)
{
Rectangle r = scContentBounds;
r.X = tmi.TickPoint.X + pt.X;
r.Width = (int)TickmarkLayout.MajorInterval + 1;
if (br == null)
{
using (Brush br2 = astyle.AlternateBackground.GetBrush(r))
g.FillRectangle(br2, r);
}
else
{
g.FillRectangle(br, r);
}
}
}
}
#endregion
#endregion
#region RenderStripes
internal override void RenderStripes(ChartRenderInfo renderInfo, Rectangle scContentBounds)
{
if (AxisStripes.Count > 0)
{
Graphics g = renderInfo.Graphics;
ChartXy chartXy = Parent as ChartXy;
Point pt = chartXy.GetLocalAdjustedPoint(Point.Empty);
foreach (AxisStripe stripe in AxisStripes)
{
if (stripe.IsDisplayed == true)
{
if (stripe.MinValue != stripe.MaxValue)
{
int x1 = chartXy.GetDataPointX(this, stripe.MinValue);
int x2 = chartXy.GetDataPointX(this, stripe.MaxValue);
Rectangle r = scContentBounds;
r.X = (x1 + pt.X);
r.Width = (x2 - x1);
RenderStripe(g, r, stripe);
}
}
}
}
}
#endregion
#region UpdateRangeValues
internal override void UpdateRangeValues(ChartXy chartXy)
{
bool seriesSeen = false;
foreach (ChartSeries series in chartXy.ChartSeries)
{
if (series.AxisX == this)
{
if (series.SeriesPoints.Count > 0)
UpdateRangeValuesEx(chartXy, series, ref seriesSeen);
}
}
if (seriesSeen == false)
{
foreach (ChartSeries series in chartXy.ChartSeries)
{
if (series.AxisX == null)
{
if (series.SeriesPoints.Count > 0)
UpdateRangeValuesEx(chartXy, series, ref seriesSeen);
}
}
}
}
#region UpdateRangeValuesEx
private void UpdateRangeValuesEx(ChartXy chartXy, ChartSeries series, ref bool seriesSeen)
{
if (ActualMinValue == null)
{
ActualMinValue = series.MinValueX;
ActualMaxValue = series.MaxValueX;
}
else
{
if (chartXy.DataCompare(series.MinValueX, ActualMinValue) < 0)
ActualMinValue = series.MinValueX;
if (chartXy.DataCompare(series.MaxValueX, ActualMaxValue) > 0)
ActualMaxValue = series.MaxValueX;
}
if (seriesSeen == false)
{
seriesSeen = true;
ScaleType = series.ActualScaleTypeX;
}
else
{
if (series.ActualScaleTypeX != ScaleType)
{
string s = "XAxis cannot contain series with differing ScaleTypes";
if (String.IsNullOrEmpty(Name) == false)
s += " (" + Name + ")";
throw new Exception(s);
}
}
if (ScaleType == ScaleType.Qualitative)
{
if (series.IsRotated == true)
{
foreach (object o in series.QualitativeYValues)
{
if (QualitativeValues.Contains(o) == false)
QualitativeValues.Add(o);
}
}
else
{
foreach (object o in series.QualitativeXValues)
{
if (QualitativeValues.Contains(o) == false)
QualitativeValues.Add(o);
}
}
if (QualitativeValues.Count - 1 > (int)ActualMaxValue)
ActualMaxValue = QualitativeValues.Count - 1;
}
}
#endregion
#endregion
#region GetValueFromPoint
internal override object GetValueFromPoint(TickmarkLayout layout, Point pt)
{
if (layout.Ticks != null)
{
pt = GetChartPoint(pt);
TickmarkTick lastTick = null;
foreach (TickmarkTick tick in layout.Ticks)
{
if (tick.TickPoint.X == pt.X)
return (tick.Value);
if (tick.TickPoint.X > pt.X)
{
if (lastTick != null)
{
double d = ((double)tick.TickPoint.X - lastTick.TickPoint.X) / (layout.MinorCount + 1);
for (int i = 1; i <= layout.MinorCount; i++)
{
int x = (int)(lastTick.TickPoint.X + (d * i));
if (x >= pt.X)
break;
}
}
break;
}
lastTick = tick;
}
int dx = pt.X - Bounds.X;
switch (ScaleType)
{
case ScaleType.Qualitative:
return (layout.MajorSpacing * ((dx + layout.MarginOffset) /
layout.MajorInterval) + (int)layout.BaseValue);
case ScaleType.DateTime:
return (GetDateTimePointValue(layout, dx));
default:
return (layout.MajorSpacing * ((dx + layout.MarginOffset) /
layout.MajorInterval) + Convert.ToDouble(layout.BaseValue));
}
}
return (null);
}
#endregion
#region GetPointFromValue
/// <summary>
/// Gets the chart Point from the given axis data value.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public override Point GetPointFromValue(object value)
{
return (new Point(GetDisplayValue(value), 0));
}
#endregion
#region GetDisplayValue
internal override int GetDisplayValue(object axisValue)
{
ChartXy chartXy = Parent as ChartXy;
return (chartXy.GetDataPointX(this, axisValue));
}
#endregion
#region EnsureVisible
/// <summary>
/// Ensures the given data value is visible and
/// optionally centered on screen.
/// </summary>
/// <param name="value"></param>
public override void EnsureVisible(object value, bool center)
{
ChartXy chartXy = Parent as ChartXy;
if (chartXy != null)
{
if (chartXy.ChartControl != null)
{
if (chartXy.ChartControl.LayoutValid == false)
chartXy.ChartControl.UpdateLayout();
Rectangle cbounds = chartXy.ContentBounds;
int x = GetDisplayValue(value);
if (center == true)
{
int n = (x - cbounds.Width / 2) - cbounds.X;
chartXy.HScrollOffset = n;
}
else
{
int n = cbounds.X + chartXy.HScrollOffset + 20;
if (x < n)
{
chartXy.HScrollOffset += (x - n);
}
else
{
n = cbounds.Right + chartXy.HScrollOffset - 20;
if (x > n)
chartXy.HScrollOffset += (x - n);
}
}
}
}
}
#endregion
#region Copy/CopyTo
/// <summary>
/// Creates a copy of the axis.
/// </summary>
/// <returns></returns>
public override ChartVisualElement Copy()
{
ChartAxisX copy = new ChartAxisX();
CopyTo(copy);
return (copy);
}
/// <summary>
/// Copies the current axis properties to the
/// given "copy" axis.
/// </summary>
/// <param name="copy"></param>
public override void CopyTo(ChartVisualElement copy)
{
ChartAxisX c = copy as ChartAxisX;
if (c != null)
{
base.CopyTo(c);
MajorGridLines.CopyTo(c.MajorGridLines);
MinorGridLines.CopyTo(c.MinorGridLines);
MajorTickmarks.CopyTo(c.MajorTickmarks);
MinorTickmarks.CopyTo(c.MinorTickmarks);
}
}
#endregion
#region GetSerialData
internal override SerialElementCollection GetSerialData(string serialName)
{
SerialElementCollection sec = new SerialElementCollection();
if (serialName != null)
{
if (serialName.Equals("") == true)
serialName = "ChartAxisX";
sec.AddStartElement(serialName);
}
sec.AddElement(MajorGridLines.GetSerialData("MajorGridLines"));
sec.AddElement(MinorGridLines.GetSerialData("MinorGridLines"));
sec.AddElement(MajorTickmarks.GetSerialData("MajorTickmarks"));
sec.AddElement(MinorTickmarks.GetSerialData("MinorTickmarks"));
sec.AddElement(base.GetSerialData(null));
if (serialName != null)
sec.AddEndElement(serialName);
return (sec);
}
#endregion
#region PutSerialData
#region ProcessCollection
internal override void ProcessCollection(SerialElement se)
{
SerialElementCollection sec = se.Sec;
switch (se.Name)
{
case "MajorGridLines":
sec.PutSerialData(MajorGridLines);
break;
case "MinorGridLines":
sec.PutSerialData(MinorGridLines);
break;
case "MajorTickmarks":
sec.PutSerialData(MajorTickmarks);
break;
case "MinorTickmarks":
sec.PutSerialData(MinorTickmarks);
break;
default:
base.ProcessCollection(se);
break;
}
}
#endregion
#endregion
}
#endregion
#region ChartAxisY
/// <summary>
/// Represents a Y-Axis element.
/// </summary>
[TypeConverter(typeof(BlankExpandableObjectConverter))]
public class ChartAxisY : ChartAxis
{
#region Constructors
public ChartAxisY()
: base(AxisOrientation.Y)
{
}
public ChartAxisY(string name)
: base(AxisOrientation.Y)
{
Name = name;
}
public ChartAxisY(string name, object minValue, object maxValue)
: base(AxisOrientation.Y)
{
Name = name;
MinValue = minValue;
MaxValue = MaxValue;
}
#endregion
#region Public properties
#region MajorGridLines
///<summary>
/// Gets the axis MajorGridLines element.
///</summary>
[Description("Indicates the MajorGridLines element.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public override ChartMajorGridLines MajorGridLines
{
get
{
if (_MajorGridLines == null)
{
_MajorGridLines = new ChartMajorGridLinesY();
_MajorGridLines.Parent = this;
}
return (_MajorGridLines);
}
}
#endregion
#region MajorTickmarks
///<summary>
/// Gets the axis MajorTickmarks element.
///</summary>
[Description("Indicates the MajorTickmarks element.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public override MajorTickmarks MajorTickmarks
{
get
{
if (_MajorTickmarks == null)
{
_MajorTickmarks = new MajorTickmarksY();
_MajorTickmarks.Parent = this;
}
return (_MajorTickmarks);
}
}
#endregion
#region MinorGridLines
///<summary>
/// Gets the axis MinorGridLines element.
///</summary>
[Description("Indicates the MinorGridLines element.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public override ChartMinorGridLines MinorGridLines
{
get
{
if (_MinorGridLines == null)
{
_MinorGridLines = new ChartMinorGridLinesY();
_MinorGridLines.Parent = this;
}
return (_MinorGridLines);
}
}
#endregion
#region MinorTickmarks
///<summary>
/// Gets the axis MinorTickmarks element.
///</summary>
[Description("Indicates the MinorTickmarks element.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public override MinorTickmarks MinorTickmarks
{
get
{
if (_MinorTickmarks == null)
{
_MinorTickmarks = new MinorTickmarksY();
_MinorTickmarks.Parent = this;
}
return (_MinorTickmarks);
}
}
#endregion
#endregion
#region MeasureOverride
protected override void MeasureOverride(ChartLayoutInfo layoutInfo)
{
ChartXy chartXy = Parent as ChartXy;
ChartAxisVisualStyle astyle = EffectiveAxisStyle;
AxisAlignment axisAlignment = GetAxisAlignment();
Rectangle bounds = layoutInfo.LayoutBounds;
if (Visible == true)
{
MeasureTitle(layoutInfo, axisAlignment);
int height = Math.Max(layoutInfo.LayoutBounds.Height, Dpi.Height((chartXy.MinContentSize.Height)));
int tickmarkLen = MeasureTickmarks(layoutInfo, height);
bounds.Width = GetMeasuredWidth();
layoutInfo.LayoutBounds.Width -= tickmarkLen;
if (axisAlignment == AxisAlignment.Far)
{
layoutInfo.LayoutBounds.X += tickmarkLen;
}
else
{
bounds.X = layoutInfo.LayoutBounds.Right;
if (EdgeAxis == true)
{
bounds.X -= 1;
if (chartXy.DropShadowDisplayed == true)
layoutInfo.LayoutBounds.Width += 3;
}
}
}
else
{
int height = Math.Max(layoutInfo.LayoutBounds.Height, Dpi.Height(chartXy.MinContentSize.Height));
int tickmarkLen = MeasureTickmarks(layoutInfo, height);
bounds.Width = 0;
}
CalcAxisBounds(layoutInfo, axisAlignment, bounds);
BoundsRelative = bounds;
base.MeasureOverride(layoutInfo);
}
#region MeasureTitle
protected void MeasureTitle(
ChartLayoutInfo layoutInfo, AxisAlignment axisAlignment)
{
if (Title.Visible == true)
{
Title.XyAlignment = (axisAlignment == AxisAlignment.Near)
? XyAlignment.Right : XyAlignment.Left;
Title.Measure(layoutInfo);
}
}
#endregion
#region MeasureTickmarks
protected virtual int MeasureTickmarks(ChartLayoutInfo layoutInfo, int height)
{
CalcMajorSpacing(layoutInfo, height);
MajorTickmarks.TickmarkLayout = TickmarkLayout;
MinorTickmarks.TickmarkLayout = TickmarkLayout;
MajorTickmarks.Measure(layoutInfo);
MinorTickmarks.Measure(layoutInfo);
return (Math.Max(MajorTickmarks.Size.Width,
MinorTickmarks.Size.Width));
}
#endregion
#region GetMeasuredWidth
private int GetMeasuredWidth()
{
int width = Math.Max(MajorTickmarks.Size.Width,
MinorTickmarks.Size.Width);
if (Title.Visible == true)
width += Title.Size.Width;
return (width);
}
#endregion
#region CalcAxisBounds
private void CalcAxisBounds(ChartLayoutInfo layoutInfo,
AxisAlignment axisAlignment, Rectangle bounds)
{
int labelWidth = 0;
int tmInnerLength = 0;
int tmOuterLength = 0;
if (TickmarkLayout.MajorCount > 0)
{
labelWidth = MajorTickmarks.GetTotalLabelWidth();
tmOuterLength = Dpi.Width(GetMaxTickMarkLength(false));
tmInnerLength = Dpi.Width(GetMaxTickMarkLength(true));
if (axisAlignment == AxisAlignment.Near)
{
if (EdgeAxis == true)
{
ChartXy chartXy = Parent as ChartXy;
if (chartXy.VScrollBar.Visible == true)
tmInnerLength += (chartXy.VScrollBar.Width + 1);
bounds.X -= tmInnerLength;
}
}
else
{
if (Title.Visible == true)
bounds.X += Title.Size.Width;
}
bounds.Width = (labelWidth + tmOuterLength + tmInnerLength + 1);
AxisBounds = bounds;
Rectangle r = bounds;
r.Width = 1;
if (axisAlignment == AxisAlignment.Near)
{
r.X += tmInnerLength;
if (EdgeAxis == false)
r.X += 1;
}
else
{
r.X = bounds.Right - tmInnerLength - 1;
}
AxisLineBounds = r;
}
}
#endregion
#endregion
#region ArrangeOverride
protected override void ArrangeOverride(ChartLayoutInfo layoutInfo)
{
ChartXy chartXy = Parent as ChartXy;
// Let the axis bounds extend into the chart's frame
// area as much as possible for better label display.
Rectangle r = AxisBounds;
r.Height = chartXy.ContentBounds.Height;
int n1 = r.Y - chartXy.FrameBounds.Y;
int n2 = chartXy.FrameBounds.Bottom - r.Bottom;
r.Y = chartXy.FrameBounds.Y;
r.Height += (n1 + n2);
AxisBounds = r;
r = AxisLineBounds;
r.Height = chartXy.ContentBounds.Height;
AxisLineBounds = r;
base.ArrangeOverride(layoutInfo);
}
#endregion
#region RenderOverride
protected override void RenderOverride(ChartRenderInfo renderInfo)
{
base.RenderOverride(renderInfo);
Graphics g = renderInfo.Graphics;
ChartAxisVisualStyle astyle = EffectiveAxisStyle;
if (TickmarkLayout.MajorCount > 0)
{
Rectangle axisBounds = GetScrollBounds(AxisBounds);
Region clip = g.Clip;
g.SetClip(axisBounds, CombineMode.Intersect);
MajorTickmarks.Render(renderInfo);
MinorTickmarks.Render(renderInfo);
RenderAxisLine(g, astyle);
g.Clip = clip;
}
}
#region RenderAxisLine
private void RenderAxisLine(Graphics g, ChartAxisVisualStyle astyle)
{
if (astyle.AxisColor.IsEmpty == false &&
astyle.AxisColor.Equals(Color.Transparent) == false)
{
Rectangle alBounds = GetScrollBounds(AxisLineBounds);
using (Pen pen = new Pen(astyle.AxisColor, Dpi.Width1))
g.DrawLine(pen, alBounds.X, alBounds.Y, alBounds.X, alBounds.Bottom - 1);
}
}
#endregion
#endregion
#region RenderCrosshairLabel (Point)
internal override void RenderCrosshairLabel(Graphics g, Point pt)
{
TickmarkLayout layout = TickmarkLayout;
if (layout != null && layout.Ticks != null && layout.Ticks.Length > 0)
{
TickmarkTick tick = layout.Ticks[0];
CrosshairValueVisualStyle lstyle = EffectiveCrosshairLabelStyle;
string text = GetCrosshairLabel(pt, layout, tick, lstyle);
if (string.IsNullOrEmpty(text) == false)
{
Rectangle r = GetCrosshairBounds(g, text, pt, lstyle);
lstyle.RenderBackground(g, r);
lstyle.RenderBorder(g, r);
if (lstyle.DropShadow.Enabled == Tbool.True)
lstyle.DropShadow.RenderDropShadow(g, r, true, true);
using (StringFormat sf = new StringFormat())
{
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
using (Brush br = new SolidBrush(lstyle.TextColor))
g.DrawString(text, lstyle.Font, br, r, sf);
}
}
}
}
#region GetCrosshairLabel
private string GetCrosshairLabel(Point pt,
TickmarkLayout layout, TickmarkTick tick, CrosshairValueVisualStyle lstyle)
{
object value = null;
switch (ScaleType)
{
case ScaleType.DateTime:
value = GetValueFromPoint(layout, pt);
break;
case ScaleType.Qualitative:
pt = GetChartPoint(pt);
int n = (int)Math.Floor(((tick.TickPoint.Y - layout.NearMargin - layout.MarginOffset +
layout.MajorInterval / 2) - pt.Y) / (layout.MajorInterval * layout.MajorSpacing));
n += tick.Index;
if ((uint)n < QualitativeValues.Count)
value = QualitativeValues[n];
break;
case ScaleType.Quantitative:
double dvalue = (Double)GetValueFromPoint(layout, pt);
if (DotPlotAxis == true && Math.Floor(layout.MajorSpacing) == layout.MajorSpacing)
dvalue = Math.Floor(dvalue + .5);
value = dvalue;
break;
}
return (GetCrosshairLabel(value, lstyle));
}
#endregion
#region GetCrosshairBounds
private Rectangle GetCrosshairBounds(Graphics g,
string text, Point pt, CrosshairValueVisualStyle lstyle)
{
ChartXy chartXy = (ChartXy)Parent;
AxisAlignment axisalignment = GetAxisAlignment();
Rectangle r = GetScrollBounds(MajorTickmarks.LabelBounds);
ChartXyVisualStyle cstyle = chartXy.EffectiveChartStyle;
if (axisalignment == AxisAlignment.Far)
{
r.X -= cstyle.Padding.Left;
r.Width += cstyle.Padding.Left;
}
else
{
r.Width += cstyle.Padding.Right;
}
SizeF sizef = g.MeasureString(text, lstyle.Font);
int width = (int) sizef.Width + 2;
if (Visible == true)
width = Math.Min(r.Width, width);
if (axisalignment == AxisAlignment.Far)
r.X = Math.Max(r.X, r.Right - width);
r.Width = width;
r.Y = pt.Y - (int)(sizef.Height / 2) - 2 - lstyle.BorderThickness.Top;
r.Height = (int)sizef.Height;
if (lstyle.Margin.IsEmpty == false)
{
if (axisalignment == AxisAlignment.Near)
r.Y += lstyle.Margin.Top;
else
r.Y -= lstyle.Margin.Bottom;
}
if (axisalignment == AxisAlignment.Near)
r.X += (lstyle.BorderThickness.Horizontal);
else
r.X -= (lstyle.BorderThickness.Horizontal);
r.Width += lstyle.BorderThickness.Horizontal;
r.Height += lstyle.BorderThickness.Vertical;
if (lstyle.Padding.IsEmpty == false)
{
if (axisalignment == AxisAlignment.Far)
r.Y -= lstyle.Padding.Vertical;
r.Height += lstyle.Padding.Vertical;
r.X -= lstyle.Padding.Left;
r.Width += lstyle.Padding.Horizontal;
}
return (r);
}
#endregion
#endregion
#region RenderCrosshairLabel (CrosshairPoint)
internal override void RenderCrosshairLabel(Graphics g, CrosshairPoint cp)
{
if ((DotPlotAxis == true) ||
(cp.SeriesPoint.ValueY == null || cp.SeriesPoint.ValueY.Length == 0))
{
RenderCrosshairLabel(g, cp.Point);
}
else
{
CrosshairValueVisualStyle lstyle = EffectiveCrosshairLabelStyle;
string text = (cp.ChartSeries.IsRotated == true)
? GetCrosshairLabel(cp.SeriesPoint.ValueX, lstyle)
: GetCrosshairLabel(cp.SeriesPoint.ValueY[cp.ValueIndex], lstyle);
if (string.IsNullOrEmpty(text) == false)
{
Rectangle r = GetCrosshairBounds(g, text, cp.Point, lstyle);
lstyle.RenderBackground(g, r);
lstyle.RenderBorder(g, r);
if (lstyle.DropShadow.Enabled == Tbool.True)
lstyle.DropShadow.RenderDropShadow(g, r, true, true);
using (StringFormat sf = new StringFormat())
{
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
using (Brush br = new SolidBrush(lstyle.TextColor))
g.DrawString(text, lstyle.Font, br, r, sf);
}
}
}
}
#endregion
#region RenderBackground
internal override void RenderBackground(ChartRenderInfo renderInfo, Rectangle scContentBounds)
{
if (UseAlternateBackground == true)
{
if (TickmarkLayout.Ticks != null)
{
Graphics g = renderInfo.Graphics;
ChartXy chartXy = Parent as ChartXy;
Point pt = chartXy.GetLocalAdjustedPoint(Point.Empty);
if (ScaleType == ScaleType.Qualitative)
pt.Y -= (int)(TickmarkLayout.MajorInterval / 2);
ChartAxisVisualStyle astyle = EffectiveAxisStyle;
if (astyle.AlternateBackground.IsSolidBrush == true)
{
using (Brush br = astyle.AlternateBackground.GetBrush(Rectangle.Empty))
{
RenderAltBackground(g,
scContentBounds, pt, TickmarkLayout, astyle, br);
}
}
else
{
RenderAltBackground(g,
scContentBounds, pt, TickmarkLayout, astyle, null);
}
}
}
}
#region RenderAltBackground
private void RenderAltBackground(Graphics g, Rectangle scContentBounds,
Point pt, TickmarkLayout TickmarkLayout, ChartAxisVisualStyle astyle, Brush br)
{
foreach (TickmarkTick tmi in TickmarkLayout.Ticks)
{
double value = GetTickmarkAltValue(tmi);
int n = (int)(Math.Ceiling(value / TickmarkLayout.MajorSpacing));
if (n % 2 == 0)
{
Rectangle r = scContentBounds;
r.Y = tmi.TickPoint.Y + pt.Y;
r.Height = (int)TickmarkLayout.MajorInterval + 1;
if (br == null)
{
using (Brush br2 = astyle.AlternateBackground.GetBrush(r))
g.FillRectangle(br2, r);
}
else
{
g.FillRectangle(br, r);
}
}
}
}
#endregion
#endregion
#region RenderStripes
internal override void RenderStripes(ChartRenderInfo renderInfo, Rectangle scContentBounds)
{
if (AxisStripes.Count > 0)
{
Graphics g = renderInfo.Graphics;
ChartXy chartXy = Parent as ChartXy;
Point pt = chartXy.GetLocalAdjustedPoint(Point.Empty);
foreach (AxisStripe stripe in AxisStripes)
{
if (stripe.IsDisplayed == true)
{
int y2 = chartXy.GetDataPointY(this, stripe.MinValue);
int y1 = chartXy.GetDataPointY(this, stripe.MaxValue);
Rectangle r = scContentBounds;
r.Y = (y1 + pt.Y);
r.Height = (y2 - y1) + 1;
RenderStripe(g, r, stripe);
}
}
}
}
#endregion
#region UpdateRangeValues
internal override void UpdateRangeValues(ChartXy chartXy)
{
bool seriesSeen = false;
foreach (ChartSeries series in chartXy.ChartSeries)
{
if (series.AxisY == this)
{
if (series.SeriesPoints.Count > 0)
UpdateRangeValuesEx(chartXy, series, ref seriesSeen);
}
}
if (seriesSeen == false)
{
foreach (ChartSeries series in chartXy.ChartSeries)
{
if (series.AxisY == null)
{
if (series.SeriesPoints.Count > 0)
UpdateRangeValuesEx(chartXy, series, ref seriesSeen);
}
}
}
}
#region UpdateRangeValuesEx
private void UpdateRangeValuesEx(ChartXy chartXy, ChartSeries series, ref bool seriesSeen)
{
if (ActualMinValue == null)
{
ActualMinValue = series.MinValueY;
ActualMaxValue = series.MaxValueY;
}
else
{
if (chartXy.DataCompare(series.MinValueY, ActualMinValue) < 0)
ActualMinValue = series.MinValueY;
if (chartXy.DataCompare(series.MaxValueY, ActualMaxValue) > 0)
ActualMaxValue = series.MaxValueY;
}
if (seriesSeen == false)
{
seriesSeen = true;
ScaleType = series.ActualScaleTypeY;
}
else
{
if (series.ActualScaleTypeY != ScaleType)
{
string s = "YAxis cannot contain series with differing ScaleTypes";
if (String.IsNullOrEmpty(Name) == false)
s += " (" + Name + ")";
throw new Exception(s);
}
}
if (ScaleType == ScaleType.Qualitative)
{
if (series.IsRotated == true)
{
foreach (object o in series.QualitativeXValues)
{
if (QualitativeValues.Contains(o) == false)
QualitativeValues.Add(o);
}
}
else
{
foreach (object o in series.QualitativeYValues)
{
if (QualitativeValues.Contains(o) == false)
QualitativeValues.Add(o);
}
}
if (QualitativeValues.Count - 1 > (int)ActualMaxValue)
ActualMaxValue = QualitativeValues.Count - 1;
}
}
#endregion
#endregion
#region GetValueFromPoint
internal override object GetValueFromPoint(TickmarkLayout layout, Point pt)
{
pt = GetChartPoint(pt);
TickmarkTick lastTick = null;
foreach (TickmarkTick tick in layout.Ticks)
{
if (tick.TickPoint.Y == pt.Y)
return (Convert.ToDouble(tick.Value));
if (tick.TickPoint.Y < pt.Y)
{
if (lastTick != null)
{
double d = ((double)lastTick.TickPoint.Y - tick.TickPoint.Y) / (layout.MinorCount + 1);
for (int i = 1; i <= layout.MinorCount; i++)
{
int y = (int)(lastTick.TickPoint.Y - (d * i));
if (y == pt.Y)
return (Convert.ToDouble(lastTick.Value) + (layout.MajorSpacing / (layout.MinorCount + 1) * i));
if (y < pt.Y)
break;
}
}
break;
}
lastTick = tick;
}
int dy = Bounds.Bottom - pt.Y;
switch (ScaleType)
{
case ScaleType.Qualitative:
return (layout.MajorSpacing * ((dy + layout.MarginOffset) /
layout.MajorInterval) + (int)layout.BaseValue);
case ScaleType.DateTime:
return (GetDateTimePointValue(layout, dy));
default:
return (layout.MajorSpacing * ((dy + layout.MarginOffset) /
layout.MajorInterval) + Convert.ToDouble(layout.BaseValue));
}
}
#endregion
#region GetPointFromValue
/// <summary>
/// Gets the chart Point from the given axis data value.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public override Point GetPointFromValue(object value)
{
return (new Point(0, GetDisplayValue(value)));
}
#endregion
#region GetDisplayValue
internal override int GetDisplayValue(object axisValue)
{
ChartXy chartXy = Parent as ChartXy;
return (chartXy.GetDataPointY(this, axisValue));
}
#endregion
#region EnsureVisible
/// <summary>
/// Ensures the given data value is visible and
/// optionally centered on screen.
/// </summary>
/// <param name="value"></param>
public override void EnsureVisible(object value, bool center)
{
ChartXy chartXy = Parent as ChartXy;
if (chartXy != null)
{
if (chartXy.ChartControl != null)
{
if (chartXy.ChartControl.LayoutValid == false)
chartXy.ChartControl.UpdateLayout();
Rectangle cbounds = chartXy.ContentBounds;
int y = GetDisplayValue(value);
if (center == true)
{
int n = cbounds.Y - (y - cbounds.Height / 2);
chartXy.VScrollOffset = n;
}
else
{
int n = cbounds.Y - chartXy.VScrollOffset + 20;
if (y < n)
{
chartXy.VScrollOffset += (n - y);
}
else
{
n = cbounds.Bottom - chartXy.VScrollOffset - 20;
if (y > n)
chartXy.VScrollOffset -= (y - n);
}
}
}
}
}
#endregion
#region Copy/CopyTo
/// <summary>
/// Creates a copy of the axis.
/// </summary>
/// <returns></returns>
public override ChartVisualElement Copy()
{
ChartAxisY copy = new ChartAxisY();
CopyTo(copy);
return (copy);
}
/// <summary>
/// Copies each axis property to the given "copy".
/// </summary>
/// <param name="copy"></param>
public override void CopyTo(ChartVisualElement copy)
{
ChartAxisY c = copy as ChartAxisY;
if (c != null)
{
base.CopyTo(c);
MajorGridLines.CopyTo(c.MajorGridLines);
MinorGridLines.CopyTo(c.MinorGridLines);
MajorTickmarks.CopyTo(c.MajorTickmarks);
MinorTickmarks.CopyTo(c.MinorTickmarks);
}
}
#endregion
#region GetSerialData
internal override SerialElementCollection GetSerialData(string serialName)
{
SerialElementCollection sec = new SerialElementCollection();
if (serialName != null)
{
if (serialName.Equals("") == true)
serialName = "ChartAxisY";
sec.AddStartElement(serialName);
}
sec.AddElement(MajorGridLines.GetSerialData("MajorGridLines"));
sec.AddElement(MinorGridLines.GetSerialData("MinorGridLines"));
sec.AddElement(MajorTickmarks.GetSerialData("MajorTickmarks"));
sec.AddElement(MinorTickmarks.GetSerialData("MinorTickmarks"));
sec.AddElement(base.GetSerialData(null));
if (serialName != null)
sec.AddEndElement(serialName);
return (sec);
}
#endregion
#region PutSerialData
#region ProcessCollection
internal override void ProcessCollection(SerialElement se)
{
SerialElementCollection sec = se.Sec;
switch (se.Name)
{
case "MajorGridLines":
sec.PutSerialData(MajorGridLines);
break;
case "MinorGridLines":
sec.PutSerialData(MinorGridLines);
break;
case "MajorTickmarks":
sec.PutSerialData(MajorTickmarks);
break;
case "MinorTickmarks":
sec.PutSerialData(MinorTickmarks);
break;
default:
base.ProcessCollection(se);
break;
}
}
#endregion
#endregion
}
#endregion
#region ChartAxis
[TypeConverter(typeof(BlankExpandableObjectConverter))]
abstract public class ChartAxis : ChartVisualElement
{
#region Private variables
private States _States;
private AxisOrientation _AxisOrientation = AxisOrientation.X;
private AxisAlignment _AxisAlignment = AxisAlignment.NotSet;
private SortDirection _QualitativeSortDirection = SortDirection.None;
private int _AxisMargins = -1;
private int _AxisNearMargin = -1;
private int _AxisFarMargin = -1;
private AxisStripeCollection _AxisStripes;
private object _MinValue = null;
private object _MaxValue = null;
private object _ActualMinValue;
private object _ActualMaxValue;
private double _GridSpacing;
private double _GridInterval;
private int _MinGridInterval = 10;
private AxisTitle _Title;
private ReferenceLineCollection _ReferenceLines;
private TickmarkLayout _TickmarkLayout;
private TickmarkLayout _LastTickmarkLayout;
private Rectangle _AxisBounds;
private Rectangle _AxisLineBounds;
private ChartAxisVisualStyle _ChartAxisVisualStyle;
private EffectiveStyle<ChartAxisVisualStyle> _EffectiveAxisStyle;
private CrosshairValueVisualStyle _CrosshairLabelVisualStyle;
private EffectiveStyle<CrosshairValueVisualStyle> _EffectiveCrosshairLabelStyle;
private List<object> _QualitativeValues;
private DateTimeUnits _DateTimeUnits = DateTimeUnits.Days;
private DateTimeUnits _DateTimeUnitsLimit = DateTimeUnits.Years;
private DateTimeUnits _ActualDateTimeUnits = DateTimeUnits.Days;
private ScaleType _ScaleType;
private AxisBar[] _AxisBars;
#endregion
#region Protected variables
protected MajorTickmarks _MajorTickmarks;
protected MinorTickmarks _MinorTickmarks;
protected ChartMajorGridLines _MajorGridLines;
protected ChartMinorGridLines _MinorGridLines;
#endregion
public ChartAxis(AxisOrientation orientation)
{
InitDefaultStates();
_AxisOrientation = orientation;
_EffectiveAxisStyle = new EffectiveStyle<ChartAxisVisualStyle>(this);
_EffectiveCrosshairLabelStyle = new EffectiveStyle<CrosshairValueVisualStyle>(this);
_AxisBars = new AxisBar[(int)AxisBarType.MaxBarCount];
for (int i = 0; i < _AxisBars.Length; i++)
_AxisBars[i] = new AxisBar();
}
#region InitDefaultStates
private void InitDefaultStates()
{
SetState(States.AutoCalcBarMargins, true);
SetState(States.SeriesRangeChanged, true);
SetState(States.UseAutoMinGridInterval, true);
}
#endregion
#region Public properties
#region ActualDateTimeUnits
/// <summary>
/// Gets the actual axis display units for DateTime data (as determined by
/// either the DateTimeUnits property or actual inspection of the associated data).
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DateTimeUnits ActualDateTimeUnits
{
get { return (_ActualDateTimeUnits); }
internal set { _ActualDateTimeUnits = value; }
}
#endregion
#region ActualMaxValue
/// <summary>
/// Gets the actual, axis max data value (as determined by
/// either the MaxValue property or actual inspection of the associated data).
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public object ActualMaxValue
{
get { return (_ActualMaxValue); }
internal set { _ActualMaxValue = value; }
}
#endregion
#region ActualMinValue
/// <summary>
/// Gets the actual, axis min data value (as determined by
/// either the MinValue property or actual inspection of the associated data).
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public object ActualMinValue
{
get { return (_ActualMinValue); }
internal set { _ActualMinValue = value; }
}
#endregion
#region AutoCalcBarMargins
/// <summary>
/// Gets or sets whether axis Bar Margins are calculated and used.
/// </summary>
[DefaultValue(true), Category("Appearance")]
[Description("Indicates whether axis Bar Margins are calculated and used.")]
public bool AutoCalcBarMargins
{
get { return (TestState(States.AutoCalcBarMargins)); }
set
{
if (value != AutoCalcBarMargins)
{
SetState(States.AutoCalcBarMargins, value);
OnPropertyChangedEx("AutoCalcBarMargins", VisualChangeType.Layout);
}
}
}
#endregion
#region AxisAlignment
/// <summary>
/// Gets or sets the axis alignment.
/// </summary>
[DefaultValue(AxisAlignment.NotSet), Category("Layout")]
[Description("Indicates the axis alignment.")]
public AxisAlignment AxisAlignment
{
get { return (_AxisAlignment); }
set
{
if (value != _AxisAlignment)
{
_AxisAlignment = value;
OnPropertyChangedEx("AxisAlignment", VisualChangeType.Layout);
}
}
}
#endregion
#region AxisFarMargin
///<summary>
/// Gets or sets the far/ending margin for the axis. When set ( >= 0 ), the
/// value overrides the general AxisMargins setting.
///</summary>
[DefaultValue(-1), Category("Layout")]
[Description("Indicates the far/ending margin for the axis. When set ( >= 0 ), the value overrides the general AxisMargins setting.")]
public int AxisFarMargin
{
get { return (_AxisFarMargin); }
set
{
if (value != _AxisFarMargin)
{
_AxisFarMargin = value;
OnPropertyChangedEx("AxisFarMargin", Style.VisualChangeType.Layout);
}
}
}
#endregion
#region AxisMargins
///<summary>
/// Gets or sets the near/beginning and far/ending pixel margins for the axis
/// (ignored when set to < 0).
///</summary>
[DefaultValue(-1), Category("Layout")]
[Description("Indicates the near/beginning and far/ending margins for the axis (ignored when set to < 0).")]
public int AxisMargins
{
get { return (_AxisMargins); }
set
{
if (value != _AxisMargins)
{
_AxisMargins = value;
OnPropertyChangedEx("AxisMargins", Style.VisualChangeType.Layout);
}
}
}
#endregion
#region AxisNearMargin
///<summary>
/// Gets or sets the near/beginning margin for the axis. When set ( >= 0 ), the
/// value overrides the general AxisMargins setting.
///</summary>
[DefaultValue(-1), Category("Layout")]
[Description("Indicates the near/beginning margin for the axis. When set ( >= 0 ), the value overrides the general AxisMargins setting.")]
public int AxisNearMargin
{
get { return (_AxisNearMargin); }
set
{
if (value != _AxisNearMargin)
{
_AxisNearMargin = value;
OnPropertyChangedEx("AxisNearMargin", Style.VisualChangeType.Layout);
}
}
}
#endregion
#region AxisOrientation
///<summary>
/// Gets the axis orientation (X/Y).
///</summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public AxisOrientation AxisOrientation
{
get { return (_AxisOrientation); }
}
#endregion
#region AxisStripes
/// <summary>
/// Gets a reference to the collection of AxisStripes associated with the axis.
/// </summary>
[Category("Appearance")]
[Description("Indicates the collection of AxisStripes associated with the axis.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public AxisStripeCollection AxisStripes
{
get
{
if (_AxisStripes == null)
{
_AxisStripes = new AxisStripeCollection();
_AxisStripes.CollectionChanged += AxisStripeCollectionChanged;
}
return (_AxisStripes);
}
internal set
{
if (_AxisStripes != null)
_AxisStripes.CollectionChanged -= AxisStripeCollectionChanged;
_AxisStripes = value;
if (_AxisStripes != null)
_AxisStripes.CollectionChanged += AxisStripeCollectionChanged;
}
}
#region AxisStripeCollectionChanged
void AxisStripeCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (ChartElement item in e.NewItems)
item.Parent = this;
break;
case NotifyCollectionChangedAction.Replace:
foreach (ChartElement item in e.OldItems)
item.Parent = null;
foreach (ChartElement item in e.NewItems)
item.Parent = this;
break;
case NotifyCollectionChangedAction.Remove:
foreach (ChartElement item in e.OldItems)
item.Parent = null;
break;
}
InvalidateLayout();
}
#endregion
#endregion
#region ChartAxisVisualStyle
/// <summary>
/// Gets or sets the visual style for the Axis.
/// </summary>
[Category("Style")]
[Description("Indicates the visual style for the Axis.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ChartAxisVisualStyle ChartAxisVisualStyle
{
get
{
if (_ChartAxisVisualStyle == null)
{
_ChartAxisVisualStyle = new ChartAxisVisualStyle();
StyleVisualChangeHandler(null, _ChartAxisVisualStyle);
}
return (_ChartAxisVisualStyle);
}
set
{
if (_ChartAxisVisualStyle != value)
{
ChartAxisVisualStyle oldValue = _ChartAxisVisualStyle;
_ChartAxisVisualStyle = value;
OnStyleChanged("ChartAxisVisualStyle", oldValue, value);
if (oldValue != null)
oldValue.Dispose();
}
}
}
#endregion
#region CrosshairLabelVisualStyle
/// <summary>
/// Gets or sets the visual style to be used for Crosshair elements associated with the axis.
/// </summary>
[Category("Style")]
[Description("Indicates the visual style to be used for Crosshair elements associated with the axis.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public CrosshairValueVisualStyle CrosshairLabelVisualStyle
{
get
{
if (_CrosshairLabelVisualStyle == null)
{
_CrosshairLabelVisualStyle = new CrosshairValueVisualStyle();
StyleVisualChangeHandler(null, _CrosshairLabelVisualStyle);
}
return (_CrosshairLabelVisualStyle);
}
set
{
if (_CrosshairLabelVisualStyle != value)
{
CrosshairValueVisualStyle oldValue = _CrosshairLabelVisualStyle;
_CrosshairLabelVisualStyle = value;
OnStyleChanged("CrosshairLabelVisualStyle", oldValue, value);
}
}
}
#endregion
#region DateTimeUnits
/// <summary>
/// Gets or sets the axis display units for DateTime data.
/// </summary>
[DefaultValue(DateTimeUnits.Days), Category("Data")]
[Description("Indicates the axis display units for DateTime data.")]
public DateTimeUnits DateTimeUnits
{
get { return (_DateTimeUnits); }
set
{
if (value != _DateTimeUnits)
{
_DateTimeUnits = value;
OnPropertyChangedEx("DateTimeUnits", VisualChangeType.Layout);
}
}
}
#endregion
#region DateTimeUnitsLimit
/// <summary>
/// Gets or sets the limiting axis display units for DateTime data (the
/// max DateTime units the chart will, if needed, promote the display to).
/// </summary>
[DefaultValue(DateTimeUnits.Years), Category("Data")]
[Description("Indicates the limiting axis display units for DateTime data (the max DateTime units the chart will, if needed, promote the display to).")]
public DateTimeUnits DateTimeUnitsLimit
{
get { return (_DateTimeUnitsLimit); }
set
{
if (value != _DateTimeUnitsLimit)
{
_DateTimeUnitsLimit = value;
OnPropertyChangedEx("DateTimeUnitsLimit", VisualChangeType.Layout);
}
}
}
#endregion
#region EffectiveAxisStyle
/// <summary>
/// Gets a reference to the Axis' Effective (cached, composite) style.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public ChartAxisVisualStyle EffectiveAxisStyle
{
get { return (_EffectiveAxisStyle.Style); }
}
#endregion
#region EffectiveCrosshairLabelStyle
/// <summary>
/// Gets a reference to the CrosshairLabel's Effective (cached, composite) style.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public CrosshairValueVisualStyle EffectiveCrosshairLabelStyle
{
get { return (_EffectiveCrosshairLabelStyle.Style); }
}
#endregion
#region GridInterval
///<summary>
/// Gets or sets the grid interval (the distance between MajorTickmarks, in pixels)
///</summary>
[Description("Indicates the grid interval (the distance between MajorTickmarks, in pixels).")]
[DefaultValue(0.0d), Category("Layout")]
public double GridInterval
{
get { return (_GridInterval); }
set
{
if (value != _GridInterval)
{
_GridInterval = value;
OnPropertyChangedEx("GridInterval", VisualChangeType.Layout);
}
}
}
#endregion
#region GridSpacing
///<summary>
/// Gets or sets the numerical spacing between MajorTickmarks (such as 1, 10, 100, ...).
///</summary>
[Description("Indicates the numerical spacing between MajorTickmarks (such as 1, 10, 100, ...).")]
[DefaultValue(0.0d), Category("Layout")]
public double GridSpacing
{
get { return (_GridSpacing); }
set
{
if (value != _GridSpacing)
{
_GridSpacing = value;
OnPropertyChangedEx("GridSpacing", VisualChangeType.Layout);
}
}
}
#endregion
#region IsPrimaryAxis
/// <summary>
/// Gets whether the axis is the Primary axis.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool IsPrimaryAxis
{
get { return (TestState(States.PrimaryAxis)); }
internal set { SetState(States.PrimaryAxis, value); }
}
#endregion
#region MajorGridLines
///<summary>
/// Gets the axis MajorGridLines element.
///</summary>
[Description("Indicates the MajorGridLines element."), Category("Appearance")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public virtual ChartMajorGridLines MajorGridLines
{
get { return (_MajorGridLines); }
}
#endregion
#region MajorTickmarks
///<summary>
/// Gets the axis MajorTickmarks element.
///</summary>
[Description("Indicates the MajorTickmarks element."), Category("Appearance")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public virtual MajorTickmarks MajorTickmarks
{
get { return (_MajorTickmarks); }
}
#endregion
#region MaxValue
///<summary>
/// Gets or sets the maximum axis data value.
///</summary>
[DefaultValue(null), Category("Data")]
[Description("Indicates the maximum axis data 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 MinorGridLines
///<summary>
/// Gets the axis MinorGridLines element.
///</summary>
[Description("Indicates the MinorGridLines element."), Category("Appearance")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public virtual ChartMinorGridLines MinorGridLines
{
get { return (_MinorGridLines); }
}
#endregion
#region MinGridInterval
///<summary>
/// Gets or sets the minimum grid interval size. This is the distance (in pixels)
/// between tickmark layout items.
///</summary>
[DefaultValue(10), Category("Layout")]
[Description("Indicates the minimum grid interval size. This is the distance (in pixels) between tickmark layout items.")]
public int MinGridInterval
{
get { return (_MinGridInterval); }
set
{
if (value != _MinGridInterval)
{
_MinGridInterval = value;
OnPropertyChangedEx("MinGridInterval", Style.VisualChangeType.Layout);
}
}
}
#endregion
#region MinorTickmarks
///<summary>
/// Gets the axis MinorTickmarks element.
///</summary>
[Description("Indicates the MinorTickmarks element."), Category("Appearance")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public virtual MinorTickmarks MinorTickmarks
{
get { return (_MinorTickmarks); }
}
#endregion
#region MinValue
///<summary>
/// Gets or sets the minimum axis data value.
///</summary>
[DefaultValue(null), Category("Data")]
[Description("Indicates the minimum axis data 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
#region QualitativeSortDirection
///<summary>
/// Gets or sets the sort direction for Qualitative axis values.
///</summary>
[DefaultValue(SortDirection.None), Category("Data")]
[Description("Indicates the sort direction for Qualitative axis values.")]
public SortDirection QualitativeSortDirection
{
get { return (_QualitativeSortDirection); }
set
{
if (value != _QualitativeSortDirection)
{
_QualitativeSortDirection = value;
RefreshRangeValues();
OnPropertyChangedEx("QualitativeSortDirection", VisualChangeType.Layout);
}
}
}
#endregion
#region ReferenceLines
/// <summary>
/// Gets a reference to the collection of axis Reference Lines
/// </summary>
[Category("Appearance")]
[Description("Indicates the collection of axis Reference Lines.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ReferenceLineCollection ReferenceLines
{
get
{
if (_ReferenceLines == null)
{
_ReferenceLines = new ReferenceLineCollection();
_ReferenceLines.CollectionChanged += ReferenceLineCollectionChanged;
}
return (_ReferenceLines);
}
internal set
{
if (_ReferenceLines != null)
_ReferenceLines.CollectionChanged -= ReferenceLineCollectionChanged;
_ReferenceLines = value;
if (_ReferenceLines != null)
_ReferenceLines.CollectionChanged += ReferenceLineCollectionChanged;
}
}
#region ReferenceLineCollectionChanged
void ReferenceLineCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (ChartElement item in e.NewItems)
item.Parent = this;
break;
case NotifyCollectionChangedAction.Replace:
foreach (ChartElement item in e.OldItems)
item.Parent = null;
foreach (ChartElement item in e.NewItems)
item.Parent = this;
break;
case NotifyCollectionChangedAction.Remove:
foreach (ChartElement item in e.OldItems)
item.Parent = null;
break;
}
InvalidateRender();
}
#endregion
#endregion
#region Title
///<summary>
/// Gets or sets the Axis Title.
///</summary>
[Category("Layout")]
[Description("Indicates the Axis Title.")]
[TypeConverter(typeof(BlankExpandableObjectConverter))]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public AxisTitle Title
{
get
{
if (_Title == null)
{
_Title = new AxisTitle();
_Title.Parent = this;
}
return (_Title);
}
set
{
if (value != _Title)
{
_Title = value;
_Title.Parent = (value != null) ? this : null;
OnPropertyChangedEx("Title", Style.VisualChangeType.Layout);
}
}
}
#endregion
#region UseAlternateBackground
/// <summary>
/// Gets or sets whether the axis utilizes the alternate background color.
/// </summary>
[DefaultValue(false), Category("Appearance")]
[Description("Indicates whether the axis utilizes the alternate background color.")]
public bool UseAlternateBackground
{
get { return (TestState(States.UseAlternateBackground)); }
set
{
if (value != UseAlternateBackground)
{
SetState(States.UseAlternateBackground, value);
OnPropertyChangedEx("UseAlternateBackground", VisualChangeType.Render);
}
}
}
#endregion
#region UseAutoMinGridInterval
/// <summary>
/// Gets or sets whether the auto-calculated minimum grid interval
/// will be used in determining the axis major tickmark interval.
/// </summary>
[DefaultValue(true), Category("Appearance")]
[Description("Indicates whether the auto-calculated minimum grid interval will be used in determining the axis major tickmark interval.")]
public bool UseAutoMinGridInterval
{
get { return (TestState(States.UseAutoMinGridInterval)); }
set
{
if (value != UseAutoMinGridInterval)
{
SetState(States.UseAutoMinGridInterval, value);
OnPropertyChangedEx("UseAutoMinGridInterval", VisualChangeType.Layout);
}
}
}
#endregion
#endregion
#region Internal properties
#region AxisBars
internal AxisBar[] AxisBars
{
get { return (_AxisBars); }
}
#endregion
#region AxisBounds
internal Rectangle AxisBounds
{
get { return (_AxisBounds); }
set { _AxisBounds = value; }
}
#endregion
#region AxisLineBounds
internal Rectangle AxisLineBounds
{
get { return (_AxisLineBounds); }
set { _AxisLineBounds = value; }
}
#endregion
#region DotPlotAxis
internal bool DotPlotAxis
{
get { return (TestState(States.DotPlotAxis)); }
set { SetState(States.DotPlotAxis, value); }
}
#endregion
#region EdgeAxis
internal bool EdgeAxis
{
get { return (TestState(States.EdgeAxis)); }
set { SetState(States.EdgeAxis, value); }
}
#endregion
#region LastTickmarkLayout
internal TickmarkLayout LastTickmarkLayout
{
get { return (_LastTickmarkLayout); }
set { _LastTickmarkLayout = value; }
}
#endregion
#region QualitativeValues
internal List<object> QualitativeValues
{
get
{
if (_QualitativeValues == null)
_QualitativeValues = new List<object>();
return (_QualitativeValues);
}
set { _QualitativeValues = value; }
}
#endregion
#region ScaleType
internal ScaleType ScaleType
{
get { return (_ScaleType); }
set { _ScaleType = value; }
}
#endregion
#region SeriesRangeChanged
internal bool SeriesRangeChanged
{
get { return (TestState(States.SeriesRangeChanged)); }
set { SetState(States.SeriesRangeChanged, value); }
}
#endregion
#region TickmarkLayout
internal TickmarkLayout TickmarkLayout
{
get { return(_TickmarkLayout); }
set { _TickmarkLayout = value; }
}
#endregion
#endregion
#region MeasureOverride
protected override void MeasureOverride(ChartLayoutInfo layoutInfo)
{
MeasureReferenceLines(layoutInfo);
}
protected void MeasureReferenceLines(ChartLayoutInfo layoutInfo)
{
Rectangle layoutBounds = layoutInfo.LayoutBounds;
foreach (ReferenceLine line in ReferenceLines)
{
layoutInfo.LayoutBounds = BoundsRelative;
line.Measure(layoutInfo);
}
layoutInfo.LayoutBounds = layoutBounds;
}
#endregion
#region ArrangeOverride
protected override void ArrangeOverride(ChartLayoutInfo layoutInfo)
{
if (Title.Visible == true)
Title.Arrange(layoutInfo);
MajorTickmarks.Arrange(layoutInfo);
MinorTickmarks.Arrange(layoutInfo);
MajorGridLines.TickmarkLayout = TickmarkLayout;
MinorGridLines.TickmarkLayout = TickmarkLayout;
MajorGridLines.Arrange(layoutInfo);
MinorGridLines.Arrange(layoutInfo);
ArrangeReferenceLines(layoutInfo);
}
#region ArrangeReferenceLines
private void ArrangeReferenceLines(ChartLayoutInfo layoutInfo)
{
Rectangle layoutBounds = layoutInfo.LayoutBounds;
foreach (ReferenceLine line in ReferenceLines)
{
layoutInfo.LayoutBounds = BoundsRelative;
line.Arrange(layoutInfo);
}
layoutInfo.LayoutBounds = layoutBounds;
}
#endregion
#endregion
#region RenderOverride
protected override void RenderOverride(ChartRenderInfo renderInfo)
{
ChartAxisVisualStyle astyle = EffectiveAxisStyle;
if (Title.Visible == true)
Title.Render(renderInfo);
}
#endregion
#region Render
internal override void Render(ChartRenderInfo renderInfo)
{
if (Displayed == true)
{
Rectangle bounds = GetScrollBounds(AxisBounds);
if (renderInfo.ClipRectangle.IntersectsWith(bounds))
RenderOverride(renderInfo);
}
}
#endregion
#region RenderCrosshairLabel
internal virtual void RenderCrosshairLabel(Graphics g, Point pt)
{
}
internal virtual void RenderCrosshairLabel(Graphics g, CrosshairPoint cp)
{
}
#region GetCrosshairLabel
internal string GetCrosshairLabel(object value, CrosshairValueVisualStyle lstyle)
{
string label = "";
if (value != null)
{
TickmarkLabelVisualStyle tstyle = MajorTickmarks.EffectiveLabelStyle;
try
{
switch (ScaleType)
{
case ScaleType.DateTime:
DateTime dtvalue = (DateTime)value;
if (string.IsNullOrEmpty(lstyle.TextFormat) == false)
label = dtvalue.ToString(lstyle.TextFormat);
else if (string.IsNullOrEmpty(tstyle.TextFormat) == false)
label = dtvalue.ToString(tstyle.TextFormat);
else
label = GetDateTimeLabel(dtvalue);
break;
case ScaleType.Qualitative:
if (string.IsNullOrEmpty(lstyle.TextFormat) == false)
label = string.Format(lstyle.TextFormat, value);
else if (string.IsNullOrEmpty(tstyle.TextFormat) == false)
label = string.Format(tstyle.TextFormat, value);
else
label = value.ToString();
break;
default:
double d = Convert.ToDouble(value);
if (string.IsNullOrEmpty(lstyle.TextFormat) == false)
label = d.ToString(lstyle.TextFormat);
else if (string.IsNullOrEmpty(tstyle.TextFormat) == false)
label = d.ToString(tstyle.TextFormat);
else if (value is int)
label = ((int)value).ToString();
else
label = d.ToString("F6");
break;
}
}
catch
{
}
}
ChartControl chartControl = ChartControl;
if (chartControl != null)
chartControl.DoGetCrosshairAxisLabelEvent(this, value, ref label);
return (label);
}
#endregion
#endregion
#region RenderBackground
internal virtual void RenderBackground(
ChartRenderInfo renderInfo, Rectangle scContentBounds)
{
}
#endregion
#region RenderStripes
internal virtual void RenderStripes(
ChartRenderInfo renderInfo, Rectangle scContentBounds)
{
}
#endregion
#region RenderStripe
protected void RenderStripe(
Graphics g, Rectangle bounds, AxisStripe stripe)
{
if (bounds.Width > 0 && bounds.Height > 0)
{
AxisStripeVisualStyle astyle = stripe.AxisStripeVisualStyle;
if (astyle.Background.IsEmpty == true)
{
g.FillRectangle(Brushes.LightPink, bounds);
}
else
{
using (Brush br = astyle.Background.GetBrush(bounds))
g.FillRectangle(br, bounds);
}
}
}
#endregion
#region CalcMajorSpacing
protected void CalcMajorSpacing(ChartLayoutInfo layoutInfo, int width)
{
ChartXy chartXy = Parent as ChartXy;
if (chartXy.DropShadowDisplayed == true)
width -= 3;
if (AxisOrientation == AxisOrientation.X)
{
if (chartXy.VScrollBar.Visible == true)
width -= chartXy.VScrollBar.Width;
}
else
{
if (chartXy.HScrollBar.Visible == true)
width -= chartXy.HScrollBar.Height;
}
TickmarkLayout layout = new TickmarkLayout();
layout.MinValue = GetMinValue();
layout.MaxValue = GetMaxValue();
if (layout.MinValue != null && layout.MaxValue != null)
{
ScaleType scaleType = ScaleType;
if (ScaleType == ScaleType.NotSet)
ScaleType = SeriesPoint.GetScaleType(layout.MinValue.GetType());
layout.MinorCount = MinorTickmarks.TickmarkCount;
if (ScaleType != ScaleType.NotSet)
{
switch (ScaleType)
{
case ScaleType.DateTime:
CalcMajorDateTimeSpacing(chartXy, layout, width);
break;
case ScaleType.Qualitative:
CalcMajorQualitativeSpacing(layout, width);
break;
default:
CalcMajorQuantitativeSpacing(chartXy, layout, width);
break;
}
}
if (AxisOrientation == AxisOrientation.Y)
{
if (chartXy.HScrollBar.Visible == true)
layout.MarginOffset -= chartXy.HScrollBarHeight;
}
}
TickmarkLayout = layout;
}
#region CalcMajorDateTimeSpacing
private void CalcMajorDateTimeSpacing(
ChartXy chartXy, TickmarkLayout layout, int width)
{
DateTime dtMinValue = (DateTime)layout.MinValue;
DateTime dtMaxValue = (DateTime)layout.MaxValue;
DateTime odtMinValue = dtMinValue;
if (width > 0 && dtMinValue < dtMaxValue)
{
DateTime ominValue = dtMinValue;
width = SetLayoutMargin(layout, width) - 2;
CalcDateTimeSpacing(chartXy, layout, dtMinValue, dtMaxValue, width);
if (AutoCalcBarMargins == true)
{
ChartSeries barSeries = GetBarSeries(chartXy);
if (barSeries != null)
{
if ((barSeries.IsRotated == false && AxisOrientation == AxisOrientation.X) ||
(barSeries.IsRotated == true && AxisOrientation == AxisOrientation.Y))
{
int n = (int)(width / layout.MajorCount / 2 / layout.MajorSpacing);
layout.NearMargin += n;
layout.FarMargin += n;
width -= (n * 2);
layout.MajorInterval = (double)width / layout.MajorCount;
}
}
}
else
{
layout.MajorInterval = (double)width / layout.MajorCount;
}
if (UseAutoMinGridInterval == true)
{
if (layout.MajorInterval <= 3)
layout.MajorInterval = 3;
}
dtMinValue = AdjustDateTimeBase(layout, dtMinValue);
UpdateDateTimeMargins(layout, ref dtMinValue, ref dtMaxValue);
double offset = GetDateTimeRange(ActualDateTimeUnits, dtMinValue, ominValue);
int moff = (int)((layout.MajorInterval * offset) / layout.MajorSpacing - layout.NearMargin - 1);
layout.MarginOffset = moff;
layout.MinValue = dtMinValue;
layout.MaxValue = dtMaxValue;
}
}
#region AdjustDateTimeBase
private DateTime AdjustDateTimeBase(TickmarkLayout layout, DateTime dtValue)
{
switch (ActualDateTimeUnits)
{
case DateTimeUnits.Milliseconds:
dtValue = dtValue.AddMilliseconds(-dtValue.Millisecond % layout.GridSpacing);
break;
case DateTimeUnits.Seconds:
dtValue = new DateTime(dtValue.Year, dtValue.Month, dtValue.Day, dtValue.Hour, dtValue.Minute, dtValue.Second);
dtValue = dtValue.AddSeconds(-dtValue.Second % layout.GridSpacing);
break;
case DateTimeUnits.Minutes:
dtValue = new DateTime(dtValue.Year, dtValue.Month, dtValue.Day, dtValue.Hour, dtValue.Minute, 0);
dtValue = dtValue.AddMinutes(-dtValue.Minute % layout.GridSpacing);
break;
case DateTimeUnits.Hours:
dtValue = new DateTime(dtValue.Year, dtValue.Month, dtValue.Day, dtValue.Hour, 0, 0);
dtValue = dtValue.AddHours(-dtValue.Hour % layout.GridSpacing);
break;
case DateTimeUnits.Days:
dtValue = new DateTime(dtValue.Year, dtValue.Month, dtValue.Day);
dtValue = dtValue.AddDays(-dtValue.Day % layout.GridSpacing);
break;
case DateTimeUnits.Months:
dtValue = new DateTime(dtValue.Year, dtValue.Month, 1);
dtValue = dtValue.AddMonths(-(int)(dtValue.Month % layout.GridSpacing));
break;
case DateTimeUnits.Years:
dtValue = new DateTime(dtValue.Year, 1, 1);
dtValue = dtValue.AddYears(-(int)(dtValue.Year % layout.GridSpacing));
break;
default:
dtValue = dtValue.AddTicks(-(long)(dtValue.Millisecond % layout.GridSpacing));
break;
}
return (dtValue);
}
#endregion
#region CalcDateTimeSpacing
private void CalcDateTimeSpacing(ChartXy chartXy,
TickmarkLayout layout, DateTime dtMinValue, DateTime dtMaxValue, int width)
{
DateTimeUnits adtu = DateTimeUnits;
double range = GetDateTimeRange(adtu, dtMinValue, dtMaxValue);
if (GridSpacing <= 0)
{
layout.GridSpacing = 1;
layout.MajorSpacing = layout.GridSpacing;
}
else
{
layout.GridSpacing = GridSpacing;
layout.MajorSpacing = layout.GridSpacing;
}
CalcDateTimeInterval(layout, range, width);
double minorInterval = layout.MajorInterval / (MinorTickmarks.TickmarkCount + 1);
if (minorInterval > 0)
{
ChartSeries barSeries = GetBarSeries(chartXy);
while (minorInterval < MinGridInterval)
{
if ((barSeries == null) && (int)adtu < (int)DateTimeUnitsLimit)
{
adtu = GetNextDateTimeUnit(adtu, dtMinValue, dtMaxValue);
range = GetDateTimeRange(adtu, dtMinValue, dtMaxValue);
CalcDateTimeInterval(layout, range, width);
minorInterval = layout.MajorInterval / (MinorTickmarks.TickmarkCount + 1);
}
else
{
if (GridSpacing > 0)
break;
minorInterval *= 2;
layout.MajorSpacing *= 2;
}
}
ActualDateTimeUnits = adtu;
CalcDateTimeInterval(layout, range, width);
}
}
#region CalcDateTimeInterval
private void CalcDateTimeInterval(TickmarkLayout layout, double range, int width)
{
double d = range / layout.MajorSpacing;
layout.MajorCount = (int)Math.Ceiling(d);
layout.MajorInterval = (double)width / d;
if (layout.MajorCount <= 0)
layout.MajorCount = 1;
}
#endregion
#region GetNextDateTimeUnit
private DateTimeUnits GetNextDateTimeUnit(
DateTimeUnits adtu, DateTime dtMinValue, DateTime dtMaxValue)
{
switch (adtu)
{
case DateTimeUnits.Ticks:
return (DateTimeUnits.Milliseconds);
case DateTimeUnits.Milliseconds:
return (DateTimeUnits.Seconds);
case DateTimeUnits.Seconds:
return (DateTimeUnits.Minutes);
case DateTimeUnits.Minutes:
return (DateTimeUnits.Hours);
case DateTimeUnits.Hours:
return (DateTimeUnits.Days);
case DateTimeUnits.Days:
return (DateTimeUnits.Months);
default:
return (DateTimeUnits.Years);
}
}
#endregion
#endregion
#region AddDateTimeOffset
private DateTime AddDateTimeOffset(DateTime dtValue, int offset)
{
switch (ActualDateTimeUnits)
{
case DateTimeUnits.Milliseconds:
dtValue = dtValue.AddMilliseconds(offset);
break;
case DateTimeUnits.Seconds:
dtValue = dtValue.AddSeconds(offset);
break;
case DateTimeUnits.Minutes:
dtValue = dtValue.AddMinutes(offset);
break;
case DateTimeUnits.Hours:
dtValue = dtValue.AddHours(offset);
break;
case DateTimeUnits.Days:
dtValue = dtValue.AddDays(offset);
break;
case DateTimeUnits.Months:
dtValue = dtValue.AddMonths(offset);
break;
case DateTimeUnits.Years:
dtValue = dtValue.AddYears(offset);
break;
default:
dtValue = dtValue.AddTicks(offset);
break;
}
return (dtValue);
}
#endregion
#region UpdateDateTimeMargins
private void UpdateDateTimeMargins(
TickmarkLayout layout, ref DateTime dtMinValue, ref DateTime dtMaxValue)
{
if (layout.NearMargin > 0)
{
int marginCount = (int)Math.Ceiling(layout.NearMargin / layout.MajorInterval);
layout.MajorCount += marginCount;
dtMinValue = AddDateTimeOffset(dtMinValue, -(int)(marginCount * 1)); //layout.MajorSpacing));
}
if (layout.FarMargin > 0)
{
int marginCount = (int)Math.Ceiling(layout.FarMargin / layout.MajorInterval);
layout.MajorCount += marginCount;
dtMaxValue = AddDateTimeOffset(dtMaxValue, (int)(marginCount * 1)); //layout.MajorSpacing));
}
}
#endregion
#region GetDateTimeRange
private double GetDateTimeRange(
DateTimeUnits dtu, DateTime dtMinValue, DateTime dtMaxValue)
{
TimeSpan ts = dtMaxValue - dtMinValue;
switch (dtu)
{
case DateTimeUnits.Milliseconds:
return (ts.TotalMilliseconds);
case DateTimeUnits.Seconds:
return (ts.TotalSeconds);
case DateTimeUnits.Minutes:
return (ts.TotalMinutes);
case DateTimeUnits.Hours:
return (ts.TotalHours);
case DateTimeUnits.Days:
return (ts.TotalDays);
case DateTimeUnits.Months:
return (CalcDateTimeMonths(dtMinValue, dtMaxValue));
case DateTimeUnits.Years:
return (CalcDateTimeYears(dtMinValue, dtMaxValue));
default:
return (dtMaxValue.Ticks - dtMinValue.Ticks);
}
}
#region CalcDateTimeYears
internal double CalcDateTimeYears(DateTime dtMinValue, DateTime dtMaxValue)
{
int years = dtMaxValue.Year - dtMinValue.Year;
DateTime last = dtMinValue.AddYears(years);
if (last > dtMaxValue)
{
last = last.AddYears(-1);
years--;
}
DateTime next = last.AddYears(1);
double yearDays = (next - last).Days;
double days = (dtMaxValue - last).Days;
return ((double)years + (days / yearDays));
}
#endregion
#region CalcDateTimeMonths
internal double CalcDateTimeMonths(DateTime dtMinValue, DateTime dtMaxValue)
{
// Rough estimation...
TimeSpan ts = dtMaxValue - dtMinValue;
return ((double)ts.Days / 30);
}
#endregion
#endregion
#endregion
#region CalcMajorQuantitativeSpacing
private void CalcMajorQuantitativeSpacing(
ChartXy chartXy, TickmarkLayout layout, int width)
{
Type otype = layout.MinValue.GetType();
double dminValue = Convert.ToDouble(layout.MinValue);
double dmaxValue = Convert.ToDouble(layout.MaxValue);
if (AutoCalcBarMargins == true)
{
ChartSeries barSeries = GetFullBarSeries(chartXy);
if (barSeries != null)
{
if (barSeries.IsRotated == true && AxisOrientation == AxisOrientation.X ||
barSeries.IsRotated == false && AxisOrientation == AxisOrientation.Y)
{
double origin = Convert.ToDouble((chartXy.BarOrigin ?? 0));
dminValue = Math.Min(origin, dminValue);
}
}
}
double ominValue = dminValue;
if (dminValue == dmaxValue)
dmaxValue++;
if (width > 0 && dminValue <= dmaxValue)
{
width = SetLayoutMargin(layout, width);
double range = Math.Abs(dmaxValue - dminValue);
CalcQuantitativeSpacing(chartXy, layout, range, width);
if (UseAutoMinGridInterval == true)
{
if (layout.MajorInterval < 3)
layout.MajorInterval = 3;
}
UpdateQuantitativeMargins(layout, otype, ref dminValue, ref dmaxValue);
// Make sure zero is included on the axis
int n = dminValue < 0 ? -1 : 1;
if (dminValue < 0)
dminValue -= ((dminValue % layout.MajorSpacing) + layout.MajorSpacing);
else if (dminValue > 0)
dminValue -= (dminValue % layout.MajorSpacing);
int moff = 0;
double delta = Math.Floor(Math.Abs(dminValue) / layout.MajorSpacing);
double value = (int)delta * layout.MajorSpacing * n;
double offset = Math.Abs(value - ominValue);
moff = (int)((layout.MajorInterval * offset) / layout.MajorSpacing - layout.NearMargin);
layout.MarginOffset = moff;
layout.MinValue = Convert.ChangeType(dminValue, otype);
layout.MaxValue = Convert.ChangeType(dmaxValue, otype);
}
}
#region CalcQuantitativeSpacing
void CalcQuantitativeSpacing(
ChartXy chartXy, TickmarkLayout layout, double range, int width)
{
if (GridSpacing <= 0)
{
// User has not specified a spacing, so calculate it for them based
// upon powers of 10 (10, 100, 1000, etc)
//
// MajorSpacing is set to a multiple of the GridSpacing (based upon
// the calculated minor tickmark interval)
layout.GridSpacing = Math.Pow(10, Math.Floor(Math.Log10(range / 10)));
if (layout.GridSpacing < 1)
layout.GridSpacing = 1;
if (layout.MinValue is int)
layout.GridSpacing = Math.Ceiling(layout.GridSpacing);
layout.MajorSpacing = layout.GridSpacing;
layout.MajorCount = (int)Math.Ceiling(range / layout.MajorSpacing);
layout.MajorInterval = (double)width / layout.MajorCount;
}
else
{
layout.GridSpacing = GridSpacing;
layout.MajorSpacing = layout.GridSpacing;
layout.MajorCount = (int)Math.Ceiling(range / layout.MajorSpacing);
layout.MajorInterval = (double)width / layout.MajorCount;
}
double gridInterval = GridInterval;
double pxp = (range < 1) ? width : ((double)width / range);
ChartSeries dpSeries = GetChartDotPlotSeries(chartXy);
if (dpSeries != null)
{
// Calculate the default dot plot spacing
gridInterval = CalcDotPlotSpacing(
chartXy, layout, range, ref width, dpSeries);
double count = range / layout.MajorSpacing;
layout.MajorCount = (int)Math.Ceiling(count);
pxp = (double)width / range;
DotPlotAxis = true;
}
else
{
ChartSeries barSeries = GetBarSeries(chartXy);
if (barSeries != null)
{
if ((barSeries.IsRotated == false && AxisOrientation == AxisOrientation.X) ||
(barSeries.IsRotated == true && AxisOrientation == AxisOrientation.Y))
{
int n = (int)(pxp / 2) + 1;
layout.NearMargin += n;
layout.FarMargin += n;
width -= (n * 2);
layout.MajorInterval = (double)width / layout.MajorCount;
pxp = (double)width / (range);
}
}
double minorInterval = layout.MajorInterval / (MinorTickmarks.TickmarkCount + 1);
if (minorInterval > 0)
{
while (minorInterval < MinGridInterval)
{
minorInterval *= 2;
layout.MajorSpacing *= 2;
}
}
gridInterval = layout.MajorInterval;
double dminValue = Convert.ToDouble(layout.MinValue);
double dmaxValue = Convert.ToDouble(layout.MaxValue);
double maxp = (int)(dmaxValue / layout.MajorSpacing) * layout.MajorSpacing;
if (maxp < dmaxValue)
maxp += layout.MajorSpacing;
double minp = (int)(dminValue / layout.MajorSpacing) * layout.MajorSpacing;
if (minp > dminValue)
minp -= layout.MajorSpacing;
layout.MajorCount = (int)Math.Ceiling((maxp - minp) / layout.MajorSpacing);
layout.MinValue = minp;
layout.MaxValue = maxp;
DotPlotAxis = false;
}
if (GridInterval > 0)
{
layout.MajorInterval = GridInterval;
}
else
{
if (AxisCanExpand(dpSeries) == true)
gridInterval = Math.Max(gridInterval, pxp * layout.MajorSpacing);
layout.MajorInterval = Math.Max(gridInterval, 1);
}
}
#region GetChartDotPlotSeries
private ChartSeries GetChartDotPlotSeries(ChartXy chartXy)
{
foreach (ChartSeries series in chartXy.ChartSeries)
{
if ((series.SeriesType == SeriesType.VerticalDot) ||
(series.SeriesType == SeriesType.HorizontalDot))
{
return (series);
}
}
return (null);
}
#endregion
#region CalcDotPlotSpacing
private double CalcDotPlotSpacing(ChartXy chartXy,
TickmarkLayout layout, double range, ref int width, ChartSeries dpSeries)
{
// If we previously added a default margin, back it back out
// since we are going to adjust the margin based upon the orientation
// and size of the marker
if (AxisMargins < 0)
{
width += ((layout.NearMargin * 2) - Dpi.Width10);
layout.NearMargin = Dpi.Width5;
}
Size dotSize = chartXy.GetMaxDotPlotMarkerSize();
DotPlotType dotTypes = chartXy.GetDotPlotTypes();
return (AxisOrientation == AxisOrientation.X)
? CalcXDotPlotSpacing(chartXy, layout, range, ref width, dpSeries, dotTypes, dotSize)
: CalcYDotPlotSpacing(chartXy, layout, range, ref width, dpSeries, dotTypes, dotSize);
}
#region CalcXDotPlotSpacing
private double CalcXDotPlotSpacing(ChartXy chartXy, TickmarkLayout layout,
double range, ref int width, ChartSeries dpSeries, DotPlotType dotTypes, Size dotSize)
{
if ((dotTypes & DotPlotType.Vertical) == DotPlotType.Vertical)
{
int n = dotSize.Width / 2;
layout.NearMargin += n;
width -= (n * 2);
}
layout.MajorSpacing = (GridSpacing <= 0) ? 1 : GridSpacing;
double gridInterval = Math.Max(layout.MajorSpacing, 1) * dotSize.Width;
if (MinGridInterval > 0)
{
while (gridInterval < Dpi.Width(MinGridInterval))
{
gridInterval *= 2;
layout.MajorSpacing *= 2;
}
}
Size size = chartXy.MinQualitativeSize;
double count = range;
if ((dotTypes & DotPlotType.Vertical) == DotPlotType.Vertical)
count = range / dpSeries.DotPlotIndexValue;
size.Width = (int)(dotSize.Width * count + layout.NearMargin * 2);
if (chartXy.VScrollBar.Enabled == true)
size.Width += chartXy.VScrollBar.Width;
chartXy.MinQualitativeSize = size;
return (gridInterval);
}
#endregion
#region CalcYDotPlotSpacing
private double CalcYDotPlotSpacing(ChartXy chartXy, TickmarkLayout layout,
double range, ref int width, ChartSeries dpSeries, DotPlotType dotTypes, Size dotSize)
{
if ((dotTypes & DotPlotType.Horizontal) == DotPlotType.Horizontal)
{
int n = dotSize.Height / 2;
layout.NearMargin += n;
width -= (n * 2);
}
layout.MajorSpacing = (GridSpacing <= 0) ? 1 : GridSpacing;
double gridInterval = layout.MajorSpacing * dotSize.Height;
if (MinGridInterval > 0)
{
while (gridInterval < MinGridInterval)
{
gridInterval *= 2;
layout.MajorSpacing *= 2;
}
}
Size size = chartXy.MinQualitativeSize;
double count = range;
if ((dotTypes & DotPlotType.Horizontal) == DotPlotType.Horizontal)
count = range / dpSeries.DotPlotIndexValue;
size.Height = (int)(dotSize.Height * count + layout.NearMargin * 2);
if (chartXy.HScrollBar.Enabled == true)
size.Height += chartXy.HScrollBar.Height;
chartXy.MinQualitativeSize = size;
return (gridInterval);
}
#endregion
#endregion
#region AxisCanExpand
private bool AxisCanExpand(ChartSeries dpSeries)
{
return ((dpSeries == null) ||
(AxisOrientation == AxisOrientation.X && dpSeries.SeriesType == SeriesType.VerticalDot) ||
(AxisOrientation == AxisOrientation.Y && dpSeries.SeriesType == SeriesType.HorizontalDot));
}
#endregion
#endregion
#region UpdateQuantitativeMargins
private void UpdateQuantitativeMargins(
TickmarkLayout layout, Type otype, ref double dminValue, ref double dmaxValue)
{
if (layout.NearMargin > 0)
{
int marginCount = (int)Math.Ceiling(layout.NearMargin / layout.MajorInterval);
layout.MajorCount += marginCount;
if (otype == typeof(Int32))
{
if (dminValue - (marginCount * layout.MajorSpacing) > Int32.MinValue)
dminValue -= (marginCount * layout.MajorSpacing);
}
else
{
dminValue -= (marginCount * layout.MajorSpacing);
}
}
if (layout.FarMargin > 0)
{
int marginCount = (int)Math.Ceiling(layout.FarMargin / layout.MajorInterval);
layout.MajorCount += marginCount;
if (otype == typeof(Int32))
{
if (dmaxValue + (marginCount * layout.MajorSpacing) < Int32.MaxValue)
dmaxValue += (marginCount * layout.MajorSpacing);
}
else
{
dmaxValue += (marginCount * layout.MajorSpacing);
}
}
}
#endregion
#endregion
#region CalcMajorQualitativeSpacing
private void CalcMajorQualitativeSpacing(TickmarkLayout layout, int width)
{
int iminValue = (int)layout.MinValue;
int imaxValue = (int)layout.MaxValue;
int ominValue = iminValue;
if (width > 0 && iminValue <= imaxValue)
{
width = SetLayoutMargin(layout, width);
double range = Math.Abs(imaxValue - iminValue) + 1;
CalcQualitativeSpacing(layout, range, width);
if (UseAutoMinGridInterval == true)
{
if (layout.MajorInterval <= 3)
layout.MajorInterval = 3;
}
UpdateQualitativeMargins(layout, ref iminValue, ref imaxValue);
// Make sure zero is included on the axis
iminValue -= (int)(iminValue % layout.MajorSpacing);
int moff = 0;
int n = iminValue < 0 ? -1 : 1;
double delta = Math.Floor(Math.Abs(iminValue) / layout.GridSpacing);
double value = (int)delta * layout.GridSpacing * n;
double offset = Math.Abs(value - ominValue);
moff = (int)((layout.MajorInterval * offset) / layout.MajorSpacing - layout.NearMargin);
layout.MarginOffset = moff;
layout.MinValue = iminValue;
layout.MaxValue = imaxValue;
}
}
#region CalcQualitativeSpacing
private void CalcQualitativeSpacing(
TickmarkLayout layout, double range, int width)
{
ChartXy chartXy = Parent as ChartXy;
layout.GridSpacing = 1;
layout.MajorSpacing = layout.GridSpacing;
layout.MajorCount = (int)range;
layout.MajorInterval = (double)width / layout.MajorCount;
if (layout.MinorCount > 0)
{
double minorInterval = layout.MajorInterval / (layout.MinorCount + 1);
if (minorInterval > 0)
{
while (minorInterval < MinGridInterval)
{
minorInterval *= 2;
layout.MinorCount /= 2;
}
}
}
List<int> groupIds = GetSeriesGroupIds(chartXy);
int colWidth = int.MinValue;
foreach (int groupId in groupIds)
{
int n = chartXy.GetQualitativeColumnWidth(this, groupId);
if (n > colWidth)
colWidth = n;
}
if (UseAutoMinGridInterval == false)
{
if (colWidth > layout.MajorInterval)
colWidth = (int)layout.MajorInterval;
}
if (colWidth < MinGridInterval)
colWidth = MinGridInterval;
int minWidth = colWidth * (layout.MajorCount);
if (AxisOrientation == AxisOrientation.X)
{
if (chartXy.MinQualitativeSize.Width != minWidth)
{
Size size = chartXy.MinQualitativeSize;
size.Width = minWidth + layout.NearMargin;
chartXy.MinQualitativeSize = size;
// Force a layout change when the next
// layout invalidation arrives
LastTickmarkLayout = null;
}
}
else
{
if (chartXy.MinQualitativeSize.Height != minWidth)
{
Size size = chartXy.MinQualitativeSize;
size.Height = minWidth + layout.NearMargin;
chartXy.MinQualitativeSize = size;
LastTickmarkLayout = null;
}
}
width += layout.NearMargin;
minWidth = Math.Max(width, minWidth) - layout.NearMargin;
layout.MajorInterval = (double)minWidth / layout.MajorCount;
if (layout.MajorInterval < MinGridInterval)
{
layout.MajorInterval = MinGridInterval;
minWidth = (int)(layout.MajorInterval * (layout.MajorCount - 0));
}
layout.MajorInterval = (double)minWidth / (layout.MajorCount - 0);
foreach (int groupId in groupIds)
{
chartXy.AdjustQualitativeOffsets(this,
groupId, colWidth, (int)(layout.MajorInterval));
}
layout.NearMargin += (int)(layout.MajorInterval / 2);
}
#region GetSeriesGroupIds
private List<int> GetSeriesGroupIds(ChartXy chartXy)
{
List<int> groupIds = new List<int>();
foreach (ChartSeries series in chartXy.ChartSeries)
{
if (groupIds.Contains(series.GroupId) == false)
groupIds.Add(series.GroupId);
}
return (groupIds);
}
#endregion
#endregion
#region UpdateQualitativeMargins
private void UpdateQualitativeMargins(
TickmarkLayout layout, ref int iminValue, ref int imaxValue)
{
if (layout.NearMargin > 0)
{
int marginCount = (int)Math.Ceiling(layout.NearMargin / layout.MajorInterval);
layout.MajorCount += marginCount;
iminValue -= (int)(marginCount * layout.MajorSpacing);
}
if (layout.FarMargin > 0)
{
int marginCount = (int)Math.Ceiling(layout.FarMargin / layout.MajorInterval);
layout.MajorCount += marginCount;
imaxValue += (int)(marginCount * layout.MajorSpacing);
}
}
#endregion
#endregion
#region SetLayoutMargin
private int SetLayoutMargin(TickmarkLayout layout, int width)
{
layout.NearMargin = (AxisNearMargin >= 0) ? AxisNearMargin : AxisMargins >= 0 ? AxisMargins : 20;
layout.FarMargin = (AxisFarMargin >= 0) ? AxisFarMargin : AxisMargins >= 0 ? AxisMargins : 20;
layout.NearMargin = Dpi.Width(layout.NearMargin);
layout.FarMargin = Dpi.Width(layout.FarMargin);
layout.NearMargin = Math.Min(layout.NearMargin, width / 3);
layout.FarMargin = Math.Min(layout.FarMargin, width / 3);
if (layout.NearMargin > 0)
width -= (layout.NearMargin + 1);
if (layout.FarMargin > 0)
width -= (layout.FarMargin + 1);
return (width);
}
#endregion
#region GetBarSeries
private ChartSeries GetBarSeries(ChartXy chartXy)
{
foreach (ChartSeries series in chartXy.ChartSeries)
{
if (series.Visible == true)
{
if (series.IsBarSeries == true)
return (series);
}
}
return (null);
}
#endregion
#region GetFullBarSeries
private ChartSeries GetFullBarSeries(ChartXy chartXy)
{
foreach (ChartSeries series in chartXy.ChartSeries)
{
if (series.Visible == true)
{
if (series.SeriesType == SeriesType.HorizontalBar ||
series.SeriesType == SeriesType.VerticalBar)
{
if (AxisOrientation == AxisOrientation.X)
{
if (series.AxisX == this || (series.AxisX == null && chartXy.AxisX == this))
return (series);
}
else
{
if (series.AxisY == this || (series.AxisY == null && chartXy.AxisY == this))
return (series);
}
}
}
}
return (null);
}
#endregion
#endregion
#region GetMaxTickMarkLength
protected int GetMaxTickMarkLength(bool inner)
{
int majorLength = MajorTickmarks.GetMaxTickmarkLength(this, inner);
int minorLength = MinorTickmarks.GetMaxTickmarkLength(this, inner);
int maxlen = Math.Max(majorLength, minorLength);
return (maxlen);
}
#endregion
#region GetAxisAlignment
internal AxisAlignment GetAxisAlignment()
{
if (AxisAlignment == AxisAlignment.NotSet)
return (IsPrimaryAxis ? AxisAlignment.Near : AxisAlignment.Far);
return (AxisAlignment);
}
#endregion
#region GetMinValue
internal object GetMinValue()
{
UpdateRangeValues();
if (MinValue != null)
{
if (ScaleType != ScaleType.NotSet)
{
if (SeriesPoint.GetScaleType(MinValue.GetType()) != ScaleType)
{
if (IsDesignerHosted == false)
throw new Exception("MinValue ScaleType must match Axis ScaleType");
return (ActualMinValue);
}
}
return (MinValue);
}
return (ActualMinValue);
}
#endregion
#region GetMaxValue
internal object GetMaxValue()
{
UpdateRangeValues();
if (MaxValue != null)
{
if (ScaleType != ScaleType.NotSet)
{
if (SeriesPoint.GetScaleType(MaxValue.GetType()) != ScaleType)
{
if (IsDesignerHosted == false)
throw new Exception("MaxValue ScaleType must match Axis ScaleType");
return (ActualMaxValue);
}
}
return (MaxValue);
}
return (ActualMaxValue);
}
#endregion
#region UpdateRangeValues
internal void UpdateRangeValues()
{
if (SeriesRangeChanged == true)
{
SeriesRangeChanged = false;
ActualMinValue = null;
ActualMaxValue = null;
QualitativeValues.Clear();
ChartXy chartXy = Parent as ChartXy;
if (chartXy != null)
{
if (chartXy.ChartSeries.Count > 0)
{
UpdateRangeValues(chartXy);
if (QualitativeValues.Count > 1)
{
if (QualitativeSortDirection != SortDirection.None)
{
QualitativeValues.Sort(new
ObjComparer(this, QualitativeSortDirection == SortDirection.Ascending));
}
}
}
}
}
}
internal virtual void UpdateRangeValues(ChartXy chartXy)
{
}
#region ObjComparer
private class ObjComparer : IComparer<object>
{
private ChartVisualElement _ChartElement;
private ChartControl _ChartControl;
private bool _Ascending;
public ObjComparer(ChartVisualElement chartElement, bool ascending)
{
_ChartElement = chartElement;
_ChartControl = chartElement.ChartControl;
_Ascending = ascending;
}
public int Compare(object v1, object v2)
{
int sval = 0;
if (_ChartControl.DoCompareElementsEvent(_ChartElement, v1, v2, ref sval) == true)
return (sval);
if (v1 is IComparable)
{
sval = ((IComparable)v1).CompareTo(v2);
if (sval != 0)
return (_Ascending == true) ? sval : -sval;
}
return (sval);
}
}
#endregion
#endregion
#region ValidateAxis
internal bool ValidateAxis()
{
bool altered = false;
if (LastTickmarkLayout == null || TickmarkLayout == null)
altered = true;
else if ((TickmarkLayout.MinValue != LastTickmarkLayout.MinValue) ||
(TickmarkLayout.MaxValue != LastTickmarkLayout.MaxValue) ||
(TickmarkLayout.MajorInterval != LastTickmarkLayout.MajorInterval) ||
(TickmarkLayout.MajorSpacing != LastTickmarkLayout.MajorSpacing) ||
(TickmarkLayout.MarginOffset != LastTickmarkLayout.MarginOffset))
{
altered = true;
}
LastTickmarkLayout = TickmarkLayout;
return (altered);
}
#endregion
#region GetChartPoint
protected Point GetChartPoint(Point pt)
{
ChartXy chartXy = Parent as ChartXy;
pt.X += ScrollOffset.X;
pt.X -= (chartXy.HScrollBar.Inverted == true ? chartXy.HScrollOffset : -chartXy.HScrollOffset);
pt.Y += ScrollOffset.Y;
pt.Y -= (chartXy.VScrollBar.Inverted == true ? chartXy.VScrollOffset : -chartXy.VScrollOffset);
return (pt);
}
#endregion
#region GetDisplayValue
virtual internal int GetDisplayValue(object axisValue)
{
return (0);
}
#endregion
#region GetDateTime
internal DateTime GetDateTime(DateTime dt, double delta)
{
switch (ActualDateTimeUnits)
{
case DateTimeUnits.Milliseconds:
return (dt.AddMilliseconds(delta));
case DateTimeUnits.Seconds:
return (dt.AddSeconds(delta));
case DateTimeUnits.Minutes:
return (dt.AddMinutes(delta));
case DateTimeUnits.Hours:
return (dt.AddHours(delta));
case DateTimeUnits.Days:
return (dt.AddDays(delta));
case DateTimeUnits.Months:
dt = dt.AddMonths((int)delta);
dt = dt.AddDays((delta - (int)delta) * 31);
return (dt);
case DateTimeUnits.Years:
return (dt.AddYears((int)delta));
default:
return (dt.AddTicks((long)delta));
}
}
#endregion
#region GetDateTimeValue
internal long GetDateTimeValue(DateTime dtValue)
{
switch (ActualDateTimeUnits)
{
case DateTimeUnits.Milliseconds:
return (dtValue.Millisecond);
case DateTimeUnits.Seconds:
return (dtValue.Second);
case DateTimeUnits.Minutes:
return (dtValue.Minute);
case DateTimeUnits.Hours:
return (dtValue.Hour);
case DateTimeUnits.Days:
return (dtValue.Day);
case DateTimeUnits.Months:
return (dtValue.Month);
case DateTimeUnits.Years:
return (dtValue.Year);
default:
return (dtValue.Ticks);
}
}
#endregion
#region GetDateTimePointValue
internal DateTime GetDateTimePointValue(TickmarkLayout layout, int dz)
{
double delta = (double)(layout.MajorSpacing * ((dz + layout.MarginOffset) / layout.MajorInterval));
return (GetDateTime((DateTime)layout.BaseValue, delta));
}
#endregion
#region GetDateTimeLabel
internal string GetDateTimeLabel(DateTime dt)
{
switch (ActualDateTimeUnits)
{
case DateTimeUnits.Ticks:
return (dt.Ticks.ToString());
case DateTimeUnits.Milliseconds:
return (dt.Millisecond.ToString());
case DateTimeUnits.Seconds:
return (dt.Second.ToString());
case DateTimeUnits.Minutes:
return (dt.Minute.ToString());
case DateTimeUnits.Hours:
return (dt.ToShortTimeString());
case DateTimeUnits.Days:
return (dt.ToShortDateString());
case DateTimeUnits.Months:
return (dt.Month + "/" + dt.Year);
default:
return (dt.Year.ToString());
}
}
#endregion
#region GetTickmarkAltValue
internal double GetTickmarkAltValue(TickmarkTick tick)
{
switch (ScaleType)
{
case ScaleType.DateTime:
DateTime dt = AddDateTimeOffset((DateTime)tick.Value, (int)(TickmarkLayout.MajorSpacing / 2));
return (GetDateTimeValue(dt));
case ScaleType.Qualitative:
return ((int)tick.Value + TickmarkLayout.MajorSpacing / 2);
default:
return (Convert.ToDouble(tick.Value) + TickmarkLayout.MajorSpacing / 2);
}
}
#endregion
#region GetLegendData
internal void GetLegendData(List<ChartLegendItem> legendData)
{
foreach (ReferenceLine line in ReferenceLines)
{
if (line.Visible == true)
{
List<ChartLegendItem> items = line.GetLegendItems();
if (items != null && items.Count > 0)
legendData.AddRange(items);
}
}
foreach (AxisStripe stripe in AxisStripes)
{
if (stripe.Visible == true)
{
List<ChartLegendItem> items = stripe.GetLegendItems();
if (items != null && items.Count > 0)
legendData.AddRange(items);
}
}
}
#endregion
#region GetPointFromValue
/// <summary>
/// Gets the chart Point from the given data value.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public virtual Point GetPointFromValue(object value)
{
return (Point.Empty);
}
#endregion
#region GetValueFromPoint
/// <summary>
/// Gets the "Data" value from the given Chart Point.
/// </summary>
/// <param name="pt"></param>
/// <returns></returns>
public object GetValueFromPoint(Point pt)
{
TickmarkLayout layout = TickmarkLayout;
return (GetValueFromPoint(layout, pt));
}
internal virtual object GetValueFromPoint(TickmarkLayout layout, Point pt)
{
return (null);
}
#endregion
#region GetReferenceLineByName
/// <summary>
/// Gets the ReferenceLine from the given name.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public ReferenceLine GetReferenceLineByName(string name)
{
if (String.IsNullOrEmpty(name) == true)
return (null);
if (_ReferenceLines != null)
{
foreach (ReferenceLine line in _ReferenceLines)
{
if (name.Equals(line.Name) == true)
return (line);
}
}
return (null);
}
#endregion
#region GetStripeByName
/// <summary>
/// Gets the AxisStripe from the given name.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public AxisStripe GetStripeByName(string name)
{
if (String.IsNullOrEmpty(name) == true)
return (null);
if (_AxisStripes != null)
{
foreach (AxisStripe stripe in _AxisStripes)
{
if (name.Equals(stripe.Name) == true)
return (stripe);
}
}
return (null);
}
#endregion
#region EnsureVisible
/// <summary>
/// Ensures the given data value is visible on screen.
/// </summary>
/// <param name="value"></param>
public void EnsureVisible(object value)
{
EnsureVisible(value, false);
}
/// <summary>
/// Ensures the given data value is visible and
/// optionally centered on screen.
/// </summary>
/// <param name="value"></param>
public virtual void EnsureVisible(object value, bool center)
{
}
#endregion
#region Style Support
#region ApplyStyles
public override void ApplyStyles(BaseVisualStyle style)
{
ChartAxisVisualStyle astyle = style as ChartAxisVisualStyle;
if (astyle != null)
{
ApplyParentStyles(astyle, Parent as ChartContainer);
astyle.ApplyStyle(ChartAxisVisualStyle);
astyle.ApplyDefaults();
}
else if (style is CrosshairValueVisualStyle)
{
CrosshairValueVisualStyle cstyle = (CrosshairValueVisualStyle)style;
ApplyParentStyles(cstyle, Parent as ChartContainer);
cstyle.ApplyStyle(CrosshairLabelVisualStyle);
cstyle.ApplyDefaults();
}
}
#region ApplyParentStyles (ChartAxisVisualStyle)
private void ApplyParentStyles(
ChartAxisVisualStyle astyle, ChartContainer item)
{
if (item != null)
{
ApplyParentStyles(astyle, item.Parent as ChartContainer);
ChartPanel cp = item as ChartPanel;
if (cp != null)
{
if (_AxisOrientation == AxisOrientation.X)
astyle.ApplyStyle(cp.DefaultVisualStyles.ChartXAxisVisualStyle);
else
astyle.ApplyStyle(cp.DefaultVisualStyles.ChartYAxisVisualStyle);
}
}
else
{
if (_AxisOrientation == AxisOrientation.X)
{
astyle.ApplyStyle(ChartControl.BaseVisualStyles.ChartXAxisVisualStyle);
astyle.ApplyStyle(ChartControl.DefaultVisualStyles.ChartXAxisVisualStyle);
}
else
{
astyle.ApplyStyle(ChartControl.BaseVisualStyles.ChartYAxisVisualStyle);
astyle.ApplyStyle(ChartControl.DefaultVisualStyles.ChartYAxisVisualStyle);
}
}
}
#endregion
#region ApplyParentStyles (CrosshairLabelVisualStyle)
private void ApplyParentStyles(
CrosshairValueVisualStyle pstyle, ChartContainer item)
{
if (item != null)
{
ApplyParentStyles(pstyle, item.Parent as ChartContainer);
if (item is ChartPanel)
pstyle.ApplyStyle(((ChartPanel)item).DefaultVisualStyles.CrosshairLabelVisualStyle);
else if (item is ChartXy)
pstyle.ApplyStyle(((ChartXy)item).ChartCrosshair.CrosshairLabelVisualStyle);
}
else
{
pstyle.ApplyStyle(ChartControl.BaseVisualStyles.CrosshairLabelVisualStyle);
pstyle.ApplyStyle(ChartControl.DefaultVisualStyles.CrosshairLabelVisualStyle);
}
}
#endregion
#endregion
#region InvalidateStyle
///<summary>
///Invalidate the cached Styles
///</summary>
public void InvalidateStyle()
{
ClearEffectiveStyles();
}
#endregion
#region ClearEffectiveStyles
protected override void ClearEffectiveStyles()
{
base.ClearEffectiveStyles();
_EffectiveAxisStyle.InvalidateStyle();
}
#endregion
#endregion
#region InvalidateRender
/// <summary>
/// Invalidate the axis for rendering purposes.
/// </summary>
public override void InvalidateRender()
{
base.InvalidateRender();
ChartXy chartXy = Parent as ChartXy;
if (chartXy != null)
chartXy.InvalidateRender();
}
#endregion
#region RefreshRangeValues
/// <summary>
/// Causes an invalidation and refresh of the range values for the axis.
/// </summary>
public void RefreshRangeValues()
{
SeriesRangeChanged = true;
InvalidateLayout();
}
#endregion
#region Copy/CopyTo
/// <summary>
/// Copies the axis elements to the given "copy"
/// </summary>
/// <param name="copy"></param>
public override void CopyTo(ChartVisualElement copy)
{
ChartAxis c = copy as ChartAxis;
if (c != null)
{
base.CopyTo(c);
c.AxisAlignment = AxisAlignment;
c.AxisFarMargin = AxisFarMargin;
c.AxisMargins = AxisMargins;
c.AxisNearMargin = AxisNearMargin;
foreach (AxisStripe stripe in AxisStripes)
c.AxisStripes.Add((AxisStripe)stripe.Copy());
c.ChartAxisVisualStyle = (_ChartAxisVisualStyle != null) ? ChartAxisVisualStyle.Copy() : null;
c.CrosshairLabelVisualStyle = (_CrosshairLabelVisualStyle != null) ? CrosshairLabelVisualStyle.Copy() : null;
c.DateTimeUnits = DateTimeUnits;
c.GridInterval = GridInterval;
c.GridSpacing = GridSpacing;
c.MinGridInterval = MinGridInterval;
c.MaxValue = MaxValue;
c.MinValue = MinValue;
foreach (ReferenceLine line in ReferenceLines)
c.ReferenceLines.Add((ReferenceLine)line.Copy());
Title.CopyTo(c.Title);
c.UseAlternateBackground = UseAlternateBackground;
}
}
#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);
}
sec.AddValue("AxisAlignment", AxisAlignment, AxisAlignment.NotSet);
sec.AddValue("AxisFarMargin", AxisFarMargin, -1);
sec.AddValue("AxisMargins", AxisMargins, -1);
sec.AddValue("AxisNearMargin", AxisNearMargin, -1);
if (_AxisStripes != null && _AxisStripes.Count > 0)
{
sec.AddStartElement("AxisStripes count=\"" + _AxisStripes.Count + "\"");
foreach (AxisStripe stripe in _AxisStripes)
sec.AddElement(stripe.GetSerialData(""));
sec.AddEndElement("AxisStripes");
}
if (_ChartAxisVisualStyle != null && _ChartAxisVisualStyle.IsEmpty == false)
sec.AddElement(_ChartAxisVisualStyle.GetSerialData("ChartAxisVisualStyle"));
if (_CrosshairLabelVisualStyle != null && _CrosshairLabelVisualStyle.IsEmpty == false)
sec.AddElement(_CrosshairLabelVisualStyle.GetSerialData("CrosshairLabelVisualStyle"));
sec.AddValue("DateTimeUnits", DateTimeUnits, DateTimeUnits.Days);
sec.AddValue("GridInterval", GridInterval, 0.0d);
sec.AddValue("GridSpacing", GridSpacing, 0.0d);
sec.AddValue("MinGridInterval", MinGridInterval, 10);
sec.AddDataValue("MaxValue", MaxValue, null);
sec.AddDataValue("MinValue", MinValue, null);
sec.AddValue("QualitativeSortDirection", QualitativeSortDirection, SortDirection.None);
if (_ReferenceLines != null && _ReferenceLines.Count > 0)
{
sec.AddStartElement("ReferenceLines count=\"" + _ReferenceLines.Count + "\"");
foreach (ReferenceLine rline in _ReferenceLines)
sec.AddElement(rline.GetSerialData(""));
sec.AddEndElement("ReferenceLines");
}
if (_Title != null)
sec.AddElement(_Title.GetSerialData("Title"));
sec.AddValue("UseAlternateBackground", UseAlternateBackground, false);
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 "AxisAlignment":
AxisAlignment = (AxisAlignment)se.GetValueEnum(typeof(AxisAlignment));
break;
case "AxisFarMargin":
AxisFarMargin = int.Parse(se.StringValue);
break;
case "AxisMargins":
AxisMargins = int.Parse(se.StringValue);
break;
case "AxisNearMargin":
AxisNearMargin = int.Parse(se.StringValue);
break;
case "DateTimeUnits":
DateTimeUnits = (DateTimeUnits)se.GetValueEnum(typeof(DateTimeUnits));
break;
case "GridInterval":
GridInterval = double.Parse(se.StringValue);
break;
case "GridSpacing":
GridSpacing = double.Parse(se.StringValue);
break;
case "MinGridInterval":
MinGridInterval = int.Parse(se.StringValue);
break;
case "MaxValue":
MaxValue = se.DataValue;
break;
case "MinValue":
MinValue = se.DataValue;
break;
case "QualitativeSortDirection":
QualitativeSortDirection = (SortDirection)se.GetValueEnum(typeof(SortDirection));
break;
case "UseAlternateBackground":
UseAlternateBackground = 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 "AxisStripes":
case "ReferenceLines":
sec.PutSerialData(this);
break;
case "AxisStripe":
AxisStripe stripe = GetStripeByName(se.Name);
if (stripe != null)
sec.PutSerialData(stripe);
break;
case "ChartAxisVisualStyle":
sec.PutSerialData(ChartAxisVisualStyle);
break;
case "CrosshairLabelVisualStyle":
sec.PutSerialData(CrosshairLabelVisualStyle);
break;
case "ReferenceLine":
ReferenceLine line = GetReferenceLineByName(se.Name);
if (line != null)
sec.PutSerialData(line);
break;
case "Title":
sec.PutSerialData(Title);
break;
default:
base.ProcessCollection(se);
break;
}
}
#endregion
#endregion
#region States
[Flags]
private enum States : uint
{
AutoCalcBarMargins = (1U << 0),
DotPlotAxis = (1U << 1),
EdgeAxis = (1U << 2),
PrimaryAxis = (1U << 3),
SeriesRangeChanged = (1U << 4),
UseAlternateBackground = (1U << 5),
UseAutoMinGridInterval = (1U << 6),
}
#region TestState
private bool TestState(States state)
{
return ((_States & state) == state);
}
#endregion
#region SetState
private void SetState(States state, bool value)
{
if (value == true)
_States |= state;
else
_States &= ~state;
}
#endregion
#endregion
#region ToString
public override string ToString()
{
if (String.IsNullOrEmpty(Name) == false)
return (Name);
return (base.ToString());
}
#endregion
#region IDisposable
public override void Dispose()
{
AxisStripes = null;
ChartAxisVisualStyle = null;
CrosshairLabelVisualStyle = null;
ReferenceLines = null;
Title = null;
base.Dispose();
}
#endregion
}
#endregion
#region TickmarkLayout
internal class TickmarkLayout
{
public object MinValue;
public object MaxValue;
public object BaseValue;
public int NearMargin;
public int FarMargin;
public int MarginOffset;
public int MajorCount;
public int MinorCount;
public double GridSpacing;
public double MajorSpacing;
public double MajorInterval;
public int TickmarkStart;
public int TickmarkEnd;
public TickmarkTick[] Ticks;
}
#endregion
#region TickmarkTick
internal class TickmarkTick
{
public int Index;
public object Value;
public Point TickPoint;
public string Label;
public Size LabelSize;
public Point LabelPoint;
public int LabelIndex;
public Color LabelColor;
public SizeF TextSize;
public bool LabelVisible;
}
#endregion
#region AxisBar
internal class AxisBar
{
public int BarCount;
public int BarOffset;
public int BarTotalWidth;
public double BarTotal;
public void Reset()
{
BarCount = 0;
BarTotal = 0;
BarTotalWidth = 0;
BarOffset = int.MinValue;
}
}
#endregion
public class AxisTitle : ChartTitle
{
#region XyAlignment
[Browsable(false)]
[Bindable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never)]
public new XyAlignment XyAlignment
{
get { return (base.XyAlignment); }
set { base.XyAlignment = value; }
}
#endregion
}
[Obsolete]
public class AsixTitle : AxisTitle
{
}
#region Enums
#region AxisAlignment
public enum AxisAlignment
{
/// <summary>
/// Default is determined by the Axis (X/Y).
/// </summary>
NotSet = -1,
/// <summary>
/// Axis is displayed at the right or bottom side of the chart.
/// </summary>
Near,
/// <summary>
/// Axis is displayed at the left or top side of the chart.
/// </summary>
Far,
}
#endregion
#region AxisBarType
internal enum AxisBarType
{
Bar,
HiLoBar,
MaxBarCount
}
#endregion
#region AxisOrientation
/// <summary>
/// AxisOrientation.
/// </summary>
public enum AxisOrientation
{
/// <summary>
/// X Axis
/// </summary>
X,
/// <summary>
/// Y Axis
/// </summary>
Y,
}
#endregion
#region DateTimeUnits
/// <summary>
/// DateTimeUnits
/// </summary>
public enum DateTimeUnits
{
Ticks,
Milliseconds,
Seconds,
Minutes,
Hours,
Days,
Months,
Years,
}
#endregion
#region MarginLayout
public enum MarginLayout
{
/// <summary>
/// No Margins will be displayed.
/// </summary>
None,
/// <summary>
/// Margin is displayed at the right or bottom side of the axis.
/// </summary>
Near,
/// <summary>
/// Margin is displayed at the left or top side of the axis.
/// </summary>
Far,
/// <summary>
/// Both Near and Far margins are displayed.
/// </summary>
Both,
}
#endregion
#region OriginOffsetMode
/// <summary>
/// Mode for setting the axis origin, or offset from its
/// normal position.
/// </summary>
public enum OriginOffsetMode
{
/// <summary>
/// No offset
/// </summary>
None,
/// <summary>
/// Origin is shifted by an absolute amount (OriginOffset)
/// </summary>
Absolute,
/// <summary>
/// Origin is shifted relative to the major scale amounts.
/// </summary>
Relative,
/// <summary>
/// Origin is shifted a percentage of the total axis length.
/// </summary>
Percent,
}
#endregion
#region OverlapLabelMode
public enum OverlapLabelMode
{
/// <summary>
/// Default is to Hide overlapping labels.
/// </summary>
NotSet = 0,
/// <summary>
/// Overlapping labels will be staggered.
/// </summary>
Stagger,
/// <summary>
/// Overlapping labels may be hidden.
/// </summary>
Hide,
}
#endregion
#endregion
}