801 lines
22 KiB
C#

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