using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using DevComponents.DotNetBar.Charts.Style;
namespace DevComponents.DotNetBar.Charts
{
#region MajorTickmarks
#region MajorTickmarksX
///
/// Represents a chart MajorTickmark on the X-Axis.
///
public class MajorTickmarksX : MajorTickmarks
{
public MajorTickmarksX()
: base(AxisOrientation.X)
{
}
#region MeasureOverride
protected override void MeasureOverride(ChartLayoutInfo layoutInfo)
{
ChartAxis chartAxis = Parent as ChartAxis;
ChartTickmarkVisualStyle tstyle = EffectiveStyle;
Rectangle bounds = Rectangle.Empty;
MeasureTickmarks(layoutInfo, chartAxis);
if (TickmarkLayout.MajorCount > 0)
{
bounds = MeasureTickmarkLabels(layoutInfo, chartAxis);
float angle = GetLabelAngle();
if (angle == 0)
CullOverlappingLabels();
}
BoundsRelative = bounds;
}
#region MeasureTickmarks
private void MeasureTickmarks(ChartLayoutInfo layoutInfo, ChartAxis chartAxis)
{
TickmarkLayout layout = TickmarkLayout;
if (layout.MajorCount > 0)
{
Graphics g = layoutInfo.Graphics;
Rectangle bounds = layoutInfo.LayoutBounds;
layout.TickmarkStart = GetStartIndex();
layout.TickmarkEnd = layout.TickmarkStart + (int)Math.Ceiling((bounds.Width + layout.MarginOffset) / layout.MajorInterval) + 3;
UpdateTickmarkTicks(g, chartAxis, bounds, layout);
ArrangeTickmarks();
}
}
#endregion
#region MeasureTickmarkLabels
private Rectangle MeasureTickmarkLabels(
ChartLayoutInfo layoutInfo, ChartAxis chartAxis)
{
ChartTickmarkVisualStyle tstyle = EffectiveStyle;
int labelHeight = GetTotalLabelHeight();
int tickmarkHeight = Dpi.Height(GetMaxTickmarkLength(chartAxis, false));
if (tickmarkHeight == 0)
tickmarkHeight = Dpi.Height4;
Rectangle bounds = layoutInfo.LayoutBounds;
bounds.Height = (labelHeight + tickmarkHeight);
ChartXy chartXy = chartAxis.Parent as ChartXy;
if (chartXy.DropShadowDisplayed == true)
bounds.Width -= 3;
Rectangle r = bounds;
if (chartAxis.GetAxisAlignment() == AxisAlignment.Far)
{
LabelBounds = new Rectangle(r.X, r.Y, r.Width, labelHeight);
r.Y += labelHeight;
r.Height -= labelHeight;
TickmarkBounds = r;
}
else
{
r.Y = layoutInfo.LayoutBounds.Bottom - labelHeight;
bounds.Y = r.Y;
LabelBounds = new Rectangle(r.X, r.Y, r.Width, labelHeight);
r.Y -= tickmarkHeight;
r.Height = tickmarkHeight;
TickmarkBounds = r;
}
if (chartAxis.EdgeAxis == false)
bounds.Height += Dpi.Height(GetMaxTickmarkLength(chartAxis, true)) + 2;
return (bounds);
}
#endregion
#endregion
#region ArrangeTickmarks
protected override void ArrangeTickmarks()
{
TickmarkLayout layout = TickmarkLayout;
if (layout.Ticks != null)
{
ChartAxis chartAxis = Parent as ChartAxis;
Rectangle tmBounds = TickmarkBounds;
Rectangle lbounds = LabelBounds;
AxisAlignment axisAlignment = chartAxis.GetAxisAlignment();
Point tickPoint = new Point(0,
(axisAlignment == AxisAlignment.Near) ? tmBounds.Y : tmBounds.Bottom + 1);
float angle = GetLabelAngle();
for (int i = layout.TickmarkStart; i < layout.TickmarkEnd; i++)
{
TickmarkTick tick = layout.Ticks[i - layout.TickmarkStart];
tickPoint.X = (int)(tmBounds.Location.X + (i * layout.MajorInterval) - layout.MarginOffset);
tick.TickPoint = tickPoint;
if (tick.Label != null)
{
tick.LabelPoint = tickPoint;
tick.LabelPoint.Y = lbounds.Y;
int height = LabelBounds.Height;
if (LabelsAreStaggered == true)
{
double value = GetTickmarkValue(chartAxis, tick);
int n = (int)(Math.Ceiling(value / TickmarkLayout.MajorSpacing));
if ((tick.Index % 2) != (axisAlignment == AxisAlignment.Far ? 0 : 1))
{
height -= MaxLabelSize[0].Height;
tick.LabelPoint.Y += MaxLabelSize[0].Height;
}
else
{
height -= MaxLabelSize[1].Height;
}
}
if (axisAlignment == AxisAlignment.Far)
tick.LabelPoint.Y += (height - tick.LabelSize.Height);
if (angle == 0)
tick.LabelPoint.X -= (tick.LabelSize.Width / 2);
}
}
}
}
#region CullOverlappingLabels
private void CullOverlappingLabels()
{
TickmarkLayout layout = TickmarkLayout;
for (int i = layout.TickmarkStart; i < layout.TickmarkEnd; i++)
{
TickmarkTick tick = layout.Ticks[i - layout.TickmarkStart];
if (tick.LabelVisible == true)
{
for (int j = i + 1; j < layout.TickmarkEnd; j++)
{
TickmarkTick tick2 = layout.Ticks[j - layout.TickmarkStart];
if (tick2.LabelVisible == true)
{
if (tick2.LabelPoint.X < tick.LabelPoint.X + tick.LabelSize.Width - 1)
{
if ((LabelsAreStaggered == false) ||
(tick.LabelIndex % 2 == tick2.LabelIndex % 2))
{
tick2.LabelVisible = false;
}
}
}
}
}
}
}
#endregion
#endregion
#region RenderOverride
protected override void RenderOverride(ChartRenderInfo renderInfo)
{
base.RenderOverride(renderInfo);
Graphics g = renderInfo.Graphics;
ChartAxis chartAxis = Parent as ChartAxis;
ChartTickmarkVisualStyle tstyle = EffectiveStyle;
if (CanRenderTickmarks(tstyle) == true)
RenderTickmarks(g, tstyle, chartAxis);
if (TickmarkLayout.MajorCount > 0)
RenderTickmarkLabels(g, chartAxis);
}
#region RenderTickmarks
private void RenderTickmarks(Graphics g,
ChartTickmarkVisualStyle tstyle, ChartAxis chartAxis)
{
SmoothingMode sm = g.SmoothingMode;
g.SmoothingMode = SmoothingMode.None;
using (Pen pen = new Pen(tstyle.TickmarkColor, Dpi.Width(tstyle.TickmarkThickness)))
{
int tlen = Dpi.Width(tstyle.TickmarkLength - ((tstyle.TickmarkThickness > 1) ? 0 : 1));
AxisAlignment axisAlignment = chartAxis.GetAxisAlignment();
Point pt = GetLocalAdjustedPoint(Point.Empty);
if ((tstyle.TickmarkAlignment == LineAlignment.Center) ||
(axisAlignment == AxisAlignment.Far && tstyle.TickmarkAlignment == LineAlignment.Near) ||
(axisAlignment == AxisAlignment.Near && tstyle.TickmarkAlignment == LineAlignment.Far))
{
// Bottom
RenderMarks(g, pen, chartAxis, pt, 0, tlen, axisAlignment == AxisAlignment.Far);
}
if ((tstyle.TickmarkAlignment == LineAlignment.Center) ||
(axisAlignment == AxisAlignment.Far && tstyle.TickmarkAlignment == LineAlignment.Far) ||
(axisAlignment == AxisAlignment.Near && tstyle.TickmarkAlignment == LineAlignment.Near))
{
// Top
ChartXy chartXy = chartAxis.Parent as ChartXy;
if (axisAlignment == AxisAlignment.Near)
{
int n = 1;
if (chartAxis.EdgeAxis == true)
n = chartXy.GetScBorderThickness(XyAlignment.Bottom) + 1;
RenderMarks(g, pen, chartAxis, pt, -(n + tlen), tlen, true);
}
else
{
int n = 1;
RenderMarks(g, pen, chartAxis, pt, -(n + tlen), tlen, false);
}
}
}
g.SmoothingMode = sm;
}
#region RenderMarks
private void RenderMarks(Graphics g,
Pen pen, ChartAxis chartAxis, Point pt, int voff, int len, bool skipFirst)
{
foreach (TickmarkTick tmi in TickmarkLayout.Ticks)
{
Point pt1 = tmi.TickPoint;
pt1.X += pt.X;
pt1.Y += (pt.Y + voff);
if (pt1.X >= chartAxis.AxisLineBounds.X - ScrollOffset.X &&
pt1.X < chartAxis.AxisLineBounds.Right - ScrollOffset.X)
{
if (tmi.Index > 0 || skipFirst == false)
{
Point pt2 = pt1;
pt2.Y += len;
g.DrawLine(pen, pt1, pt2);
}
}
}
}
#endregion
#endregion
#region RenderTickmarkLabels
private void RenderTickmarkLabels(Graphics g, ChartAxis chartAxis)
{
if (LabelBounds.IsEmpty == false)
{
TickmarkLabelVisualStyle lstyle = EffectiveLabelStyle;
Point pt = GetLocalAdjustedPoint(Point.Empty);
float angle = GetLabelAngle();
using (SolidBrush br = new SolidBrush(lstyle.TextColor))
{
SmoothingMode sm = g.SmoothingMode;
g.SmoothingMode = SmoothingMode.HighQuality;
ChartXy chartXy = chartAxis.Parent as ChartXy;
Rectangle alb = chartXy.GetScrollBounds(chartAxis.AxisLineBounds);
foreach (TickmarkTick tmi in TickmarkLayout.Ticks)
{
if (tmi.LabelVisible == true)
{
if ((tmi.TickPoint.X + pt.X >= alb.X) &&
(tmi.TickPoint.X + pt.X < alb.Right))
{
if (tmi.LabelColor.IsEmpty == true)
{
RenderLabel(g, tmi, pt, angle, br, lstyle.Font);
}
else
{
using (SolidBrush br2 = new SolidBrush(tmi.LabelColor))
RenderLabel(g, tmi, pt, angle, br2, lstyle.Font);
}
}
}
}
g.SmoothingMode = sm;
}
}
}
#region RenderLabel
private void RenderLabel(Graphics g,
TickmarkTick tmi, Point pt, float angle, Brush br, Font font)
{
Rectangle r = new Rectangle(tmi.LabelPoint, tmi.LabelSize);
r.X += pt.X;
r.Y += pt.Y;
if (angle == 0)
{
g.DrawString(tmi.Label, font, br, r);
}
else
{
Point pt1 = Point.Empty;
if (angle > 0)
{
if (angle > 90)
{
angle = angle - 180;
pt1.X = -(int)tmi.TextSize.Width;
}
pt1.Y = -(int)((Math.Abs(angle) / 90f) * (font.Height / 2));
g.TranslateTransform(r.X, r.Y);
}
else
{
if (angle < -90)
{
angle = angle + 180;
pt1.X = -(int)tmi.TextSize.Width + 4;
}
pt1.Y = -(int)(tmi.TextSize.Height -
(Math.Abs(angle) / 90f) * (tmi.TextSize.Height / 2));
g.TranslateTransform(r.X, LabelBounds.Bottom - 1);
}
g.RotateTransform(angle);
g.DrawString(tmi.Label, font, br, pt1);
g.ResetTransform();
}
}
#endregion
#endregion
#endregion
#region GetStartIndex
internal override int GetStartIndex()
{
ChartAxis chartAxis = Parent as ChartAxis;
ChartXy chartXy = chartAxis.Parent as ChartXy;
return (GetStartIndexEx(chartXy.HScrollBar));
}
#endregion
#region Copy/CopyTo
///
/// Create a copy of the chart element.
///
///
public override ChartVisualElement Copy()
{
MajorTickmarksX copy = new MajorTickmarksX();
CopyTo(copy);
return (copy);
}
///
/// Copies the chart element to the given "copy".
///
///
public override void CopyTo(ChartVisualElement copy)
{
MajorTickmarksX c = copy as MajorTickmarksX;
if (c != null)
base.CopyTo(c);
}
#endregion
}
#endregion
#region MajorTickmarksY
///
/// Represents a chart MajorTickmark on the Y-Axis.
///
public class MajorTickmarksY : MajorTickmarks
{
public MajorTickmarksY()
: base(AxisOrientation.Y)
{
}
#region MeasureOverride
protected override void MeasureOverride(ChartLayoutInfo layoutInfo)
{
ChartAxis chartAxis = Parent as ChartAxis;
ChartTickmarkVisualStyle tstyle = EffectiveStyle;
Rectangle bounds = Rectangle.Empty;
MeasureTickmarks(layoutInfo, chartAxis);
if (TickmarkLayout.MajorCount > 0)
bounds = MeasureTickmarkLabels(layoutInfo, chartAxis);
BoundsRelative = bounds;
}
#region MeasureTickmarks
private void MeasureTickmarks(ChartLayoutInfo layoutInfo, ChartAxis chartAxis)
{
TickmarkLayout layout = TickmarkLayout;
if (layout.MajorCount > 0)
{
Graphics g = layoutInfo.Graphics;
Rectangle bounds = layoutInfo.LayoutBounds;
layout.TickmarkStart = GetStartIndex();
layout.TickmarkEnd = layout.TickmarkStart + (int)((Math.Ceiling(bounds.Height / layout.MajorInterval))) + 3;
UpdateTickmarkTicks(g, chartAxis, bounds, layout);
ArrangeTickmarks();
}
}
#endregion
#region MeasureTickmarkLabels
private Rectangle MeasureTickmarkLabels(ChartLayoutInfo layoutInfo, ChartAxis chartAxis)
{
Rectangle bounds = layoutInfo.LayoutBounds;
int labelWidth = GetTotalLabelWidth();
int tickmarkWidth = Dpi.Width(GetMaxTickmarkLength(chartAxis, false));
bounds.Width = (labelWidth + tickmarkWidth);
ChartXy chartXy = chartAxis.Parent as ChartXy;
if (chartXy.DropShadowDisplayed == true)
bounds.Height -= 3;
Rectangle r = bounds;
AxisAlignment axisAlignment = chartAxis.GetAxisAlignment();
if (axisAlignment == AxisAlignment.Far)
{
LabelBounds = new Rectangle(r.X, r.Y, labelWidth, r.Height);
r.X += labelWidth;
r.Width -= labelWidth;
TickmarkBounds = r;
}
else
{
r.X = layoutInfo.LayoutBounds.Right - labelWidth;
bounds.X = r.X;
LabelBounds = new Rectangle(r.X, r.Y, labelWidth, r.Height);
r.X -= tickmarkWidth;
r.Width = tickmarkWidth;
TickmarkBounds = r;
}
if (chartAxis.EdgeAxis == false)
bounds.Width += Dpi.Width(GetMaxTickmarkLength(chartAxis, true)) + 2;
return (bounds);
}
#endregion
#endregion
#region ArrangeTickmarks
protected override void ArrangeTickmarks()
{
ChartAxis chartAxis = Parent as ChartAxis;
Rectangle tmBounds = TickmarkBounds;
Rectangle lbounds = LabelBounds;
TickmarkLayout layout = TickmarkLayout;
AxisAlignment axisAlignment = chartAxis.GetAxisAlignment();
Point tickPoint = new Point((axisAlignment == AxisAlignment.Near) ? tmBounds.X : tmBounds.Right + 1, 0);
float angle = GetLabelAngle();
for (int i = layout.TickmarkStart; i < layout.TickmarkEnd; i++)
{
TickmarkTick tick = layout.Ticks[i - layout.TickmarkStart];
tickPoint.Y = (int)(tmBounds.Bottom - 1 - (i * layout.MajorInterval) + layout.MarginOffset);
tick.TickPoint = tickPoint;
tick.LabelPoint = tickPoint;
tick.LabelPoint.X = lbounds.X;
int width = LabelBounds.Width;
if (LabelsAreStaggered == true)
{
double value = GetTickmarkValue(chartAxis, tick);
int n = (int)(Math.Ceiling(value / TickmarkLayout.MajorSpacing));
if ((n % 2) != (axisAlignment == AxisAlignment.Near ? 0 : 1))
{
width -= MaxLabelSize[0].Width;
tick.LabelPoint.X += MaxLabelSize[0].Width;
}
else
{
width -= MaxLabelSize[1].Width;
}
}
if (axisAlignment == AxisAlignment.Far)
tick.LabelPoint.X += (width - tick.LabelSize.Width);
if ((angle + 90) % 180 == 0)
tick.LabelPoint.Y -= (tick.LabelSize.Height / 2);
}
}
#endregion
#region RenderOverride
protected override void RenderOverride(ChartRenderInfo renderInfo)
{
base.RenderOverride(renderInfo);
Graphics g = renderInfo.Graphics;
ChartAxis chartAxis = Parent as ChartAxis;
ChartTickmarkVisualStyle tstyle = EffectiveStyle;
if (CanRenderTickmarks(tstyle) == true)
RenderTickmarks(g, tstyle, chartAxis);
if (TickmarkLayout.MajorCount > 0)
RenderTickmarkLabels(g, chartAxis);
}
#region RenderTickmarks
private void RenderTickmarks(Graphics g,
ChartTickmarkVisualStyle tstyle, ChartAxis chartAxis)
{
SmoothingMode sm = g.SmoothingMode;
g.SmoothingMode = SmoothingMode.None;
using (Pen pen = new Pen(tstyle.TickmarkColor, Dpi.Height(tstyle.TickmarkThickness)))
{
int tlen = Dpi.Height(tstyle.TickmarkLength) - ((tstyle.TickmarkThickness > 1) ? 0 : 1);
Point pt = GetLocalAdjustedPoint(Point.Empty);
AxisAlignment axisAlignment = chartAxis.GetAxisAlignment();
if (tstyle.TickmarkAlignment == LineAlignment.Center ||
(axisAlignment == AxisAlignment.Far && tstyle.TickmarkAlignment == LineAlignment.Near) ||
(axisAlignment == AxisAlignment.Near && tstyle.TickmarkAlignment == LineAlignment.Far))
{
// Right
RenderMarks(g, pen, chartAxis, pt, 0, tlen, axisAlignment == AxisAlignment.Far);
}
if (tstyle.TickmarkAlignment == LineAlignment.Center ||
(axisAlignment == AxisAlignment.Far && tstyle.TickmarkAlignment == LineAlignment.Far) ||
(axisAlignment == AxisAlignment.Near && tstyle.TickmarkAlignment == LineAlignment.Near))
{
// Left
ChartXy chartXy = chartAxis.Parent as ChartXy;
if (axisAlignment == AxisAlignment.Near)
{
int n = 1;
if (chartAxis.EdgeAxis == true)
n = chartXy.GetScBorderThickness(XyAlignment.Right) + 1;
RenderMarks(g, pen, chartAxis, pt, -(n + tlen), tlen, true);
}
else
{
int n = 2;
RenderMarks(g, pen, chartAxis, pt, -(n + tlen), tlen, false);
}
}
}
g.SmoothingMode = sm;
}
#region RenderMarks
private void RenderMarks(Graphics g,
Pen pen, ChartAxis chartAxis, Point pt, int hoff, int len, bool skipFirst)
{
foreach (TickmarkTick tmi in TickmarkLayout.Ticks)
{
Point pt1 = tmi.TickPoint;
pt1.X += (pt.X + hoff);
pt1.Y += pt.Y;
if (pt1.Y >= chartAxis.AxisLineBounds.Y - ScrollOffset.Y &&
pt1.Y < chartAxis.AxisLineBounds.Bottom - ScrollOffset.Y)
{
if (tmi.Index > 0 || skipFirst == false)
{
Point pt2 = pt1;
pt2.X += len;
g.DrawLine(pen, pt1, pt2);
}
}
}
}
#endregion
#endregion
#region RenderTickmarkLabels
private void RenderTickmarkLabels(Graphics g, ChartAxis chartAxis)
{
if (LabelBounds.IsEmpty == false)
{
TickmarkLabelVisualStyle lstyle = EffectiveLabelStyle;
Point pt = GetLocalAdjustedPoint(Point.Empty);
AxisAlignment axisAlignment = chartAxis.GetAxisAlignment();
float angle = GetLabelAngle();
using (SolidBrush br = new SolidBrush(lstyle.TextColor))
{
SmoothingMode sm = g.SmoothingMode;
g.SmoothingMode = SmoothingMode.HighQuality;
Rectangle bounds = chartAxis.Bounds;
foreach (TickmarkTick tmi in TickmarkLayout.Ticks)
{
if (tmi.LabelVisible == true)
{
if (tmi.TickPoint.Y + pt.Y < bounds.Y)
break;
if (tmi.TickPoint.Y + pt.Y > bounds.Bottom)
continue;
if (tmi.LabelColor.IsEmpty == true)
{
RenderLabel(g, tmi, pt, axisAlignment, angle, br, lstyle.Font);
}
else
{
using (SolidBrush br2 = new SolidBrush(tmi.LabelColor))
RenderLabel(g, tmi, pt, axisAlignment, angle, br2, lstyle.Font);
}
}
}
g.SmoothingMode = sm;
}
}
}
#region RenderLabel
private void RenderLabel(Graphics g, TickmarkTick tmi,
Point pt, AxisAlignment axisAlignment, float angle, Brush br, Font font)
{
Rectangle r = new Rectangle(tmi.LabelPoint, tmi.LabelSize);
r.X += pt.X;
r.Y += pt.Y;
int n = (int)(tmi.TextSize.Height / 2);
if (angle == 0)
{
r.Y -= n;
g.DrawString(tmi.Label, font, br, r);
}
else
{
Point pt1 = Point.Empty;
if (angle > 0)
{
if (angle > 90)
{
angle = angle - 180;
pt1.Y -= (int)(((90 + angle) / 90f) * (font.Height / 2));
}
else
{
pt1.Y -= (n + (int)((Math.Abs(angle) / 90f) * (font.Height / 2)));
}
g.TranslateTransform(r.X, r.Y);
}
else
{
if (angle < -90)
{
angle = angle + 180;
pt1.Y -= ((int)((Math.Abs(90 - angle) / 90f) * (tmi.TextSize.Height / 2)));
}
else
{
pt1.Y -= (n + (int)((Math.Abs(angle) / 90f) * (font.Height / 2)));
}
pt1.X = -(int)tmi.TextSize.Width;
g.TranslateTransform(r.Right, r.Y);
}
g.RotateTransform(angle);
g.DrawString(tmi.Label, font, br, pt1);
g.ResetTransform();
}
}
#endregion
#endregion
#endregion
#region GetStartIndex
internal override int GetStartIndex()
{
ChartAxis chartAxis = Parent as ChartAxis;
ChartXy chartXy = chartAxis.Parent as ChartXy;
return (GetStartIndexEx(chartXy.VScrollBar));
}
#endregion
#region Copy/CopyTo
///
/// Creates a copy of the chart element.
///
///
public override ChartVisualElement Copy()
{
MajorTickmarksY copy = new MajorTickmarksY();
CopyTo(copy);
return (copy);
}
///
/// Copies the chart element to the given "copy".
///
///
public override void CopyTo(ChartVisualElement copy)
{
MajorTickmarksY c = copy as MajorTickmarksY;
if (c != null)
base.CopyTo(c);
}
#endregion
}
#endregion
#region MajorTickmarks
///
/// Represents a chart MajorTickmark.
///
public class MajorTickmarks : ChartTickmarks
{
#region Private variables
private MajorStates _MajorStates;
private float _LabelAngle;
private int _MinLabelGap = 4;
private int _LabelSkip;
private Rectangle _LabelBounds;
private Size[] _MaxLabelSize;
private TickmarkLabelVisualStyle _LabelVisualStyle;
private EffectiveStyle _EffectiveLabelStyle;
#endregion
public MajorTickmarks(AxisOrientation orientation)
: base(orientation)
{
InitDefaultStates();
_EffectiveLabelStyle = new EffectiveStyle(this);
}
#region InitDefaultStates
private void InitDefaultStates()
{
SetState(MajorStates.AutoLayout, true);
SetState(MajorStates.ShowLabels, true);
SetState(MajorStates.StaggerLabels, true);
}
#endregion
#region Public properties
#region AutoTickmarkLayout
///
/// Gets or sets whether Major Tickmark layout is automatic.
///
[DefaultValue(true), Category("Appearance")]
[Description("Indicates whether Major Tickmark layout is automatic.")]
public bool AutoTickmarkLayout
{
get { return (TestState(MajorStates.AutoLayout)); }
set
{
if (value != AutoTickmarkLayout)
{
SetState(MajorStates.AutoLayout, value);
OnPropertyChangedEx("AutoTickmarkLayout", VisualChangeType.Layout);
}
}
}
#endregion
#region EffectiveLabelStyles
///
/// Gets a reference to the Tickmark Label's Effective (cached, composite) style.
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public TickmarkLabelVisualStyle EffectiveLabelStyle
{
get { return (_EffectiveLabelStyle.Style); }
}
#endregion
#region LabelAngle
///
/// Gets or sets the angle at which the Tickmark labels are displayed.
///
[DefaultValue(0f), Category("Layout")]
[Description("Indicates the angle at which the Tickmark labels are displayed.")]
[Editor("DevComponents.Charts.Design.AngleRangeValueEditor, DevComponents.Charts.Design, " +
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public float LabelAngle
{
get { return (_LabelAngle); }
set
{
if (value != _LabelAngle)
{
_LabelAngle = value;
OnPropertyChangedEx("LabelAngle", VisualChangeType.Layout);
}
}
}
#endregion
#region LabelSkip
///
/// Gets or sets the number of inter-labels to skip.
///
[DefaultValue(0), Category("Layout")]
[Description("Indicates the number of inter-labels to skip.")]
public int LabelSkip
{
get { return (_LabelSkip); }
set
{
if (value != _LabelSkip)
{
_LabelSkip = value;
OnPropertyChangedEx("LabelSkip", VisualChangeType.Layout);
}
}
}
#endregion
#region LabelVisualStyle
///
/// Gets or sets the visual style for the Tickmark Labels.
///
[Category("Style")]
[Description("Indicates the visual style for the Tickmark Labels.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public TickmarkLabelVisualStyle LabelVisualStyle
{
get
{
if (_LabelVisualStyle == null)
{
_LabelVisualStyle = new TickmarkLabelVisualStyle();
StyleVisualChangeHandler(null, _LabelVisualStyle);
}
return (_LabelVisualStyle);
}
set
{
if (_LabelVisualStyle != value)
{
TickmarkLabelVisualStyle oldValue = _LabelVisualStyle;
_LabelVisualStyle = value;
OnStyleChanged("LabelVisualStyle", oldValue, value);
if (oldValue != null)
oldValue.Dispose();
}
}
}
#endregion
#region MinLabelGap
///
/// Gets or sets the minimum gap between tickmark labels.
///
[DefaultValue(4), Category("Layout")]
[Description("Indicates the minimum gap between tickmark labels.")]
public int MinLabelGap
{
get { return (_MinLabelGap); }
set
{
if (value != _MinLabelGap)
{
_MinLabelGap = value;
OnPropertyChangedEx("MinLabelGap", VisualChangeType.Layout);
}
}
}
#endregion
#region ShowLabels
///
/// Gets or sets whether Tickmark labels are shown.
///
[DefaultValue(true), Category("Layout")]
[Description("Indicates whether Tickmark labels are shown.")]
public bool ShowLabels
{
get { return (TestState(MajorStates.ShowLabels)); }
set
{
if (value != ShowLabels)
{
SetState(MajorStates.ShowLabels, value);
OnPropertyChangedEx("ShowLabels", VisualChangeType.Layout);
}
}
}
#endregion
#region StaggerLabels
///
/// Gets or sets whether overlapping labels are staggered.
///
[DefaultValue(true), Category("Layout")]
[Description("Indicates whether overlapping labels are staggered.")]
public bool StaggerLabels
{
get { return (TestState(MajorStates.StaggerLabels)); }
set
{
if (value != StaggerLabels)
{
SetState(MajorStates.StaggerLabels, value);
OnPropertyChangedEx("StaggerLabels", VisualChangeType.Layout);
}
}
}
#endregion
#endregion
#region Internal properties
#region LabelBounds
internal Rectangle LabelBounds
{
get { return (_LabelBounds); }
set { _LabelBounds = value; }
}
#endregion
#region LabelsAreStaggered
internal bool LabelsAreStaggered
{
get { return (TestState(MajorStates.LabelsAreStaggered)); }
set { SetState(MajorStates.LabelsAreStaggered, value); }
}
#endregion
#region MaxLabelSize
internal Size[] MaxLabelSize
{
get { return (_MaxLabelSize); }
set { _MaxLabelSize = value; }
}
#endregion
#endregion
#region UpdateTickmarkTicks
internal void UpdateTickmarkTicks(Graphics g,
ChartAxis chartAxis, Rectangle bounds, TickmarkLayout layout)
{
TickmarkTick[] ticks = new TickmarkTick[layout.TickmarkEnd - layout.TickmarkStart];
CalculateBaseValue(chartAxis, layout);
if (ShowLabels == true)
{
TickmarkLabelVisualStyle lbstyle = EffectiveLabelStyle;
using (StringFormat sf = new StringFormat())
{
lbstyle.GetStringFormatFlags(sf);
if (lbstyle.MaxLineCount <= 1)
sf.FormatFlags |= StringFormatFlags.NoWrap;
int maxLabelWidth = lbstyle.MaxWidth < 0 ? 0 : lbstyle.MaxWidth;
float angle = GetLabelAngle();
int skip = (LabelSkip > 0 ? LabelSkip + 1 : 0);
for (int i = layout.TickmarkStart; i < layout.TickmarkEnd; i++)
{
TickmarkTick tmi = new TickmarkTick();
tmi.Index = i;
SetTickValue(chartAxis, layout, lbstyle, tmi);
if ((tmi.Label != null) && (skip <= 0 || (tmi.LabelIndex) % skip == 0))
{
lbstyle.GetStringFormatFlags(sf);
tmi.TextSize = g.MeasureString(tmi.Label, lbstyle.Font, maxLabelWidth, sf);
if (tmi.TextSize.IsEmpty == false)
{
tmi.TextSize.Width++;
tmi.TextSize.Height++;
}
if (lbstyle.MaxLineCount > 1)
{
int lineHeight = (int)(Math.Ceiling(lbstyle.Font.GetHeight())) * lbstyle.MaxLineCount;
if (tmi.TextSize.Height > lineHeight)
tmi.TextSize.Height = lineHeight;
}
if (angle != 0)
{
double radians = MathHelper.ToRadians(angle);
tmi.LabelSize.Width = (int)(Math.Abs(tmi.TextSize.Width * Math.Cos(radians)) + Math.Abs(tmi.TextSize.Height * Math.Sin(radians)));
tmi.LabelSize.Height = (int)(Math.Abs(tmi.TextSize.Width * Math.Sin(radians)) + Math.Abs(tmi.TextSize.Height * Math.Cos(radians)));
}
else
{
tmi.LabelSize = tmi.TextSize.ToSize();
}
tmi.LabelVisible = true;
}
else
{
tmi.LabelVisible = false;
}
ticks[i - layout.TickmarkStart] = tmi;
}
}
}
else
{
for (int i = layout.TickmarkStart; i < layout.TickmarkEnd; i++)
{
TickmarkTick tmi = new TickmarkTick();
tmi.Index = i;
SetTickValue(chartAxis, layout, null, tmi);
ticks[i - layout.TickmarkStart] = tmi;
}
}
layout.Ticks = ticks;
}
#region CalculateBaseValue
private void CalculateBaseValue(ChartAxis axis, TickmarkLayout layout)
{
switch (axis.ScaleType)
{
case ScaleType.Qualitative:
int iminValue = (int)layout.MinValue;
int ivalue = (int)Math.Floor(iminValue / layout.GridSpacing);
layout.BaseValue = (int)(ivalue * layout.GridSpacing);
break;
case ScaleType.DateTime:
layout.BaseValue = layout.MinValue;
break;
default:
Type otype = layout.MinValue.GetType();
double dminValue = Convert.ToDouble(layout.MinValue);
double n = dminValue < 0 ? -1 : 1;
double dvalue = Math.Floor(Math.Abs(dminValue) / layout.MajorSpacing);
layout.BaseValue = Convert.ChangeType((int)dvalue * layout.MajorSpacing * n, otype);
break;
}
}
#endregion
#region SetTickValue
private void SetTickValue(ChartAxis chartAxis,
TickmarkLayout layout, TickmarkLabelVisualStyle lbstyle, TickmarkTick tmi)
{
tmi.LabelIndex = -1;
switch (chartAxis.ScaleType)
{
case ScaleType.Qualitative:
tmi.Value = (int)layout.BaseValue + tmi.Index;
if (ShowLabels == true)
{
int i = (int)tmi.Value;
if ((uint)i < chartAxis.QualitativeValues.Count)
{
object value = chartAxis.QualitativeValues[i];
if (string.IsNullOrEmpty(lbstyle.TextFormat) == false)
tmi.Label = string.Format(lbstyle.TextFormat, value);
else
tmi.Label = value.ToString();
tmi.LabelIndex = i;
}
}
break;
case ScaleType.DateTime:
tmi.Value = chartAxis.GetDateTime((DateTime)layout.BaseValue, tmi.Index * layout.MajorSpacing);
if (ShowLabels == true)
{
DateTime dt = (DateTime)tmi.Value;
if (string.IsNullOrEmpty(lbstyle.TextFormat) == false)
tmi.Label = dt.ToString(lbstyle.TextFormat);
else
tmi.Label = chartAxis.GetDateTimeLabel(dt);
tmi.LabelIndex = tmi.Index;
}
break;
default:
Type otype = layout.BaseValue.GetType();
double dbase = Convert.ToDouble(layout.BaseValue);
tmi.Value = dbase + (tmi.Index * layout.MajorSpacing);
if (ShowLabels == true)
{
if (string.IsNullOrEmpty(lbstyle.TextFormat) == false)
tmi.Label = String.Format("{0:" + lbstyle.TextFormat + "}", tmi.Value);
else
tmi.Label = tmi.Value.ToString();
tmi.LabelIndex = tmi.Index;
}
break;
}
if (ShowLabels == true && tmi.LabelIndex >= 0)
{
ChartControl chartControl = ChartControl;
chartControl.DoGetTickmarkLabelEvent(chartAxis, tmi.Value, ref tmi.Label, ref tmi.LabelColor);
}
}
#endregion
#endregion
#region GetTickmarkValue
internal double GetTickmarkValue(ChartAxis chartAxis, TickmarkTick tick)
{
switch (chartAxis.ScaleType)
{
case ScaleType.DateTime:
return (chartAxis.GetDateTimeValue((DateTime)tick.Value));
case ScaleType.Qualitative:
return ((int)tick.Value + TickmarkLayout.MajorSpacing / 2);
default:
return (Convert.ToDouble(tick.Value) + TickmarkLayout.MajorSpacing / 2);
}
}
#endregion
#region GetLabelAngle
protected virtual float GetLabelAngle()
{
float angle = LabelAngle % 180;
ChartAxis chartAxis = Parent as ChartAxis;
AxisAlignment axisAlignment = chartAxis.GetAxisAlignment();
if (axisAlignment == AxisAlignment.Near)
{
if (angle < -90)
angle += 180;
}
else
{
if (angle > 0)
angle -= 180;
}
return (angle);
}
#endregion
#region GetStartIndex
internal virtual int GetStartIndex()
{
return (0);
}
internal int GetStartIndexEx(ScrollBarLite srollBar)
{
int offset = srollBar.Value;
if (offset <= 0)
return (0);
int range = TickmarkLayout.MajorCount - 1;
int smax = srollBar.Maximum;
double dx = (((double)(offset * range)) / smax);
return (int)(dx);
}
#endregion
#region ArrangeTickmarks
protected virtual void ArrangeTickmarks()
{
}
#endregion
#region ArrangeOverride
protected override void ArrangeOverride(ChartLayoutInfo layoutInfo)
{
ChartAxis axis = Parent as ChartAxis;
ChartXy chartXy = axis.Parent as ChartXy;
if (TickmarkLayout.TickmarkStart != GetStartIndex())
{
Rectangle bounds = layoutInfo.LayoutBounds;
layoutInfo.LayoutBounds = chartXy.BoundsRelative;
chartXy.Measure(layoutInfo);
chartXy.Arrange(layoutInfo);
layoutInfo.LayoutBounds = bounds;
if (layoutInfo.LayoutBoundsAdjusted == true)
{
layoutInfo.LayoutBoundsAdjusted = false;
chartXy.InvalidateRender();
}
}
ArrangeTickmarks();
}
#endregion
#region GetTotalLabelHeight
internal int GetTotalLabelHeight()
{
return (GetTotalLabelSize().Height);
}
#endregion
#region GetTotalLabelWidth
internal int GetTotalLabelWidth()
{
return (GetTotalLabelSize().Width);
}
#endregion
#region GetTotalLabelSize
internal Size GetTotalLabelSize()
{
_MaxLabelSize = new Size[2];
_MaxLabelSize[0] = Size.Empty;
_MaxLabelSize[1] = Size.Empty;
TickmarkTick lastTmi = null;
LabelsAreStaggered = false;
float angle = GetLabelAngle();
int minLabelGap = Dpi.Width(MinLabelGap);
foreach (TickmarkTick tmi in TickmarkLayout.Ticks)
{
if (tmi.LabelVisible == true && tmi.LabelPoint.IsEmpty == false && tmi.LabelIndex >= 0)
{
int n = tmi.Index % 2;
if (tmi.LabelSize.Height > _MaxLabelSize[n].Height)
_MaxLabelSize[n].Height = tmi.LabelSize.Height;
if (tmi.LabelSize.Width > _MaxLabelSize[n].Width)
_MaxLabelSize[n].Width = tmi.LabelSize.Width;
if (StaggerLabels == true && LabelsAreStaggered == false)
{
if (lastTmi != null)
{
if (AxisOrientation == AxisOrientation.X)
{
if (angle % 180 == 0)
{
if (lastTmi.LabelPoint.X +
lastTmi.LabelSize.Width + minLabelGap > tmi.LabelPoint.X)
{
LabelsAreStaggered = true;
}
}
}
else
{
if ((angle + 90) % 180 == 0)
{
if (tmi.LabelPoint.Y +
tmi.LabelSize.Height + minLabelGap > lastTmi.LabelPoint.Y)
{
LabelsAreStaggered = true;
}
}
}
}
lastTmi = tmi;
}
}
}
Size maxSize = Size.Empty;
if (LabelsAreStaggered == true)
{
if (AxisOrientation == AxisOrientation.X)
maxSize.Height = _MaxLabelSize[0].Height + _MaxLabelSize[1].Height;
else
maxSize.Width = _MaxLabelSize[0].Width + _MaxLabelSize[1].Width;
}
else
{
maxSize.Height = Math.Max(_MaxLabelSize[0].Height, _MaxLabelSize[1].Height);
maxSize.Width = Math.Max(_MaxLabelSize[0].Width, _MaxLabelSize[1].Width);
}
return (maxSize);
}
#endregion
#region Style handling
#region ApplyStyles
public override void ApplyStyles(BaseVisualStyle style)
{
base.ApplyStyles(style);
TickmarkLabelVisualStyle lstyle = style as TickmarkLabelVisualStyle;
if (lstyle != null)
{
ApplyParentStyles(lstyle, Parent as ChartContainer);
lstyle.ApplyStyle(LabelVisualStyle);
if (lstyle.Font == null)
lstyle.Font = SystemFonts.DefaultFont;
if (lstyle.TextColor.IsEmpty)
lstyle.TextColor = Color.Black;
}
}
#region ApplyParentStyles
private void ApplyParentStyles(
TickmarkLabelVisualStyle pstyle, ChartContainer item)
{
if (item != null)
{
ApplyParentStyles(pstyle, item.Parent as ChartContainer);
}
else
{
pstyle.ApplyStyle(ChartControl.BaseVisualStyles.TickmarkLabelVisualStyle);
pstyle.ApplyStyle(ChartControl.DefaultVisualStyles.TickmarkLabelVisualStyle);
}
}
#endregion
#endregion
#region ClearEffectiveStyles
protected override void ClearEffectiveStyles()
{
base.ClearEffectiveStyles();
_EffectiveLabelStyle.InvalidateStyle();
}
#endregion
#endregion
#region Copy/CopyTo
///
/// Copies the chart element to the given "copy".
///
///
public override void CopyTo(ChartVisualElement copy)
{
MajorTickmarks c = copy as MajorTickmarks;
if (c != null)
{
base.CopyTo(c);
c.AutoTickmarkLayout = AutoTickmarkLayout;
c.LabelAngle = LabelAngle;
c.LabelVisualStyle = (_LabelVisualStyle != null) ? LabelVisualStyle.Copy() : null;
c.MinLabelGap = MinLabelGap;
c.ShowLabels = ShowLabels;
c.StaggerLabels = StaggerLabels;
}
}
#endregion
#region GetSerialData
internal override SerialElementCollection GetSerialData(string serialName)
{
SerialElementCollection sec = new SerialElementCollection();
if (serialName != null)
{
if (serialName.Equals("") == true)
serialName = "MajorTickmarks";
sec.AddStartElement(serialName);
}
sec.AddValue("AutoTickmarkLayout", AutoTickmarkLayout, true);
sec.AddValue("LabelAngle", LabelAngle, 0f);
sec.AddValue("LabelSkip", LabelSkip, 0);
if (_LabelVisualStyle != null && _LabelVisualStyle.IsEmpty == false)
sec.AddElement(_LabelVisualStyle.GetSerialData("LabelVisualStyle"));
sec.AddValue("MinLabelGap", MinLabelGap, 4);
sec.AddValue("ShowLabels", ShowLabels, true);
sec.AddValue("StaggerLabels", StaggerLabels, true);
sec.AddElement(base.GetSerialData(null));
if (serialName != null)
sec.AddEndElement(serialName);
return (sec);
}
#endregion
#region PutSerialData
#region ProcessValue
internal override void ProcessValue(SerialElement se)
{
switch (se.Name)
{
case "AutoTickmarkLayout":
AutoTickmarkLayout = bool.Parse(se.StringValue);
break;
case "LabelAngle":
LabelAngle = float.Parse(se.StringValue);
break;
case "LabelSkip":
LabelSkip = int.Parse(se.StringValue);
break;
case "MinLabelGap":
MinLabelGap = int.Parse(se.StringValue);
break;
case "ShowLabels":
ShowLabels = bool.Parse(se.StringValue);
break;
case "StaggerLabels":
StaggerLabels = 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 "LabelVisualStyle":
sec.PutSerialData(LabelVisualStyle);
break;
default:
base.ProcessCollection(se);
break;
}
}
#endregion
#endregion
#region MajorStates
[Flags]
protected enum MajorStates : uint
{
AutoLayout = (1U << 0),
ShowLabels = (1U << 1),
StaggerLabels = (1U << 2),
//--------
LabelsAreStaggered = (1U << 3),
}
#region TestState
protected bool TestState(MajorStates state)
{
return ((_MajorStates & state) == state);
}
#endregion
#region SetState
protected void SetState(MajorStates state, bool value)
{
if (value == true)
_MajorStates |= state;
else
_MajorStates &= ~state;
}
#endregion
#endregion
#region IDisposable
public override void Dispose()
{
LabelVisualStyle = null;
base.Dispose();
}
#endregion
}
#endregion
#endregion
#region MinorTickmarks
#region MinorTickmarksX
///
/// Represents a Minor tickmark on the X-Axis.
///
public class MinorTickmarksX : MinorTickmarks
{
public MinorTickmarksX()
: base(AxisOrientation.X)
{
}
#region MeasureOverride
protected override void MeasureOverride(ChartLayoutInfo layoutInfo)
{
ChartAxis chartAxis = Parent as ChartAxis;
Rectangle bounds = Rectangle.Empty;
if (TickmarkCount > 0)
{
bounds = layoutInfo.LayoutBounds;
bounds.Height = Dpi.Height(GetMaxTickmarkLength(chartAxis, false));
}
BoundsRelative = bounds;
}
#endregion
#region RenderOverride
protected override void RenderOverride(ChartRenderInfo renderInfo)
{
TickmarkTick[] ticks = TickmarkLayout.Ticks;
if (ticks.Length > 1)
{
ChartAxis chartAxis = Parent as ChartAxis;
ChartTickmarkVisualStyle tstyle = EffectiveStyle;
if (CanRenderTickmarks(tstyle) == true)
{
Graphics g = renderInfo.Graphics;
Point pt = GetLocalAdjustedPoint(Point.Empty);
AxisAlignment axisAlignment = chartAxis.GetAxisAlignment();
using (Pen pen = new Pen(tstyle.TickmarkColor, Dpi.Width(tstyle.TickmarkThickness)))
{
int tlen = Dpi.Width(tstyle.TickmarkLength);
if ((tstyle.TickmarkAlignment == LineAlignment.Center) ||
(axisAlignment == AxisAlignment.Far && tstyle.TickmarkAlignment == LineAlignment.Near) ||
(axisAlignment == AxisAlignment.Near && tstyle.TickmarkAlignment == LineAlignment.Far))
{
// Bottom
RenderMarks(g, pen, chartAxis, pt, ticks, 0, tlen - 1);
}
if ((tstyle.TickmarkAlignment == LineAlignment.Center) ||
(axisAlignment == AxisAlignment.Far && tstyle.TickmarkAlignment == LineAlignment.Far) ||
(axisAlignment == AxisAlignment.Near && tstyle.TickmarkAlignment == LineAlignment.Near))
{
// Top
ChartXy chartXy = chartAxis.Parent as ChartXy;
if (axisAlignment == AxisAlignment.Near)
{
int n = 1;
if (chartAxis.EdgeAxis == true)
n = chartXy.GetScBorderThickness(XyAlignment.Bottom);
RenderMarks(g, pen, chartAxis, pt, ticks, -(n + tlen), tlen - 1);
}
else
{
int n = 0;
RenderMarks(g, pen, chartAxis, pt, ticks, -(n + tlen), tlen - 1);
}
}
}
}
}
}
#region CanRenderTickmarks
protected override bool CanRenderTickmarks(ChartTickmarkVisualStyle tstyle)
{
if (TickmarkCount <= 0)
return (false);
return (base.CanRenderTickmarks(tstyle));
}
#endregion
#region RenderMarks
private void RenderMarks(Graphics g,
Pen pen, ChartAxis chartAxis, Point pt, TickmarkTick[] ticks, int voff, int len)
{
ChartAxis axis = Parent as ChartAxis;
int minorTickCount = TickmarkLayout.MinorCount;
for (int i = 0; i < ticks.Length - 1; i++)
{
TickmarkTick tick = ticks[i];
Point pt1 = tick.TickPoint;
pt1.Y += (pt.Y + voff);
Point pt2 = pt1;
pt2.Y += len;
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;
if (pt1.X >= chartAxis.AxisLineBounds.X - ScrollOffset.X &&
pt1.X < chartAxis.AxisLineBounds.Right - ScrollOffset.X)
{
if (pt1.Equals(pt2) == true)
pt1.Y--;
g.DrawLine(pen, pt1, pt2);
}
}
}
}
#endregion
#endregion
#region Copy/CopyTo
///
/// Creates a copy of the chart element.
///
///
public override ChartVisualElement Copy()
{
MinorTickmarksX copy = new MinorTickmarksX();
CopyTo(copy);
return (copy);
}
///
/// Copies the chart element to the given "copy".
///
///
public override void CopyTo(ChartVisualElement copy)
{
MinorTickmarksX c = copy as MinorTickmarksX;
if (c != null)
{
base.CopyTo(c);
}
}
#endregion
}
#endregion
#region MinorTickmarksY
///
/// Represents a Minor tickmark on the Y-Axis.
///
public class MinorTickmarksY : MinorTickmarks
{
public MinorTickmarksY()
: base(AxisOrientation.Y)
{
}
#region MeasureOverride
protected override void MeasureOverride(ChartLayoutInfo layoutInfo)
{
ChartAxis chartAxis = Parent as ChartAxis;
Rectangle bounds = Rectangle.Empty;
if (TickmarkCount > 0)
{
bounds = layoutInfo.LayoutBounds;
bounds.Width = Dpi.Width(GetMaxTickmarkLength(chartAxis, false));
if (chartAxis.AxisAlignment == AxisAlignment.Near)
bounds.X = layoutInfo.LayoutBounds.Right - bounds.Width;
}
BoundsRelative = bounds;
}
#endregion
#region RenderOverride
protected override void RenderOverride(ChartRenderInfo renderInfo)
{
TickmarkTick[] ticks = TickmarkLayout.Ticks;
if (ticks.Length > 1)
{
ChartAxis chartAxis = Parent as ChartAxis;
ChartTickmarkVisualStyle tstyle = EffectiveStyle;
if (CanRenderTickmarks(tstyle) == true)
{
Graphics g = renderInfo.Graphics;
AxisAlignment axisAlignment = chartAxis.GetAxisAlignment();
using (Pen pen = new Pen(tstyle.TickmarkColor, Dpi.Height(tstyle.TickmarkThickness)))
{
int tlen = Dpi.Height(tstyle.TickmarkLength);
if (tstyle.TickmarkAlignment == LineAlignment.Center ||
(axisAlignment == AxisAlignment.Far && tstyle.TickmarkAlignment == LineAlignment.Near) ||
(axisAlignment == AxisAlignment.Near && tstyle.TickmarkAlignment == LineAlignment.Far))
{
// Right
RenderMarks(g, pen, chartAxis, ticks, 0, tlen - 1);
}
if (tstyle.TickmarkAlignment == LineAlignment.Center ||
(axisAlignment == AxisAlignment.Far && tstyle.TickmarkAlignment == LineAlignment.Far) ||
(axisAlignment == AxisAlignment.Near && tstyle.TickmarkAlignment == LineAlignment.Near))
{
// Left
ChartXy chartXy = chartAxis.Parent as ChartXy;
if (axisAlignment == AxisAlignment.Near)
{
int n = 1;
if (chartAxis.EdgeAxis == true)
n = chartXy.GetScBorderThickness(XyAlignment.Right);
RenderMarks(g, pen, chartAxis, ticks, -(n + tlen), tlen - 1);
}
else
{
int n = 1;
RenderMarks(g, pen, chartAxis, ticks, -(n + tlen), tlen);
}
}
}
}
}
}
#region CanRenderTickmarks
protected override bool CanRenderTickmarks(ChartTickmarkVisualStyle tstyle)
{
if (TickmarkCount <= 0)
return (false);
return (base.CanRenderTickmarks(tstyle));
}
#endregion
#region RenderMarks
private void RenderMarks(Graphics g,
Pen pen, ChartAxis chartAxis, TickmarkTick[] ticks, int hoff, int len)
{
ChartAxis axis = Parent as ChartAxis;
int minorTickCount = TickmarkLayout.MinorCount;
Point pt = GetLocalAdjustedPoint(Point.Empty);
for (int i = 0; i < ticks.Length - 1; i++)
{
TickmarkTick tick = ticks[i];
Point pt1 = tick.TickPoint;
pt1.X += (pt.X + hoff);
Point pt2 = pt1;
pt2.X += len;
double dy = (double)(ticks[i + 1].TickPoint.Y - tick.TickPoint.Y) / (minorTickCount + 1);
double ddy = dy;
for (int j = 0; j < minorTickCount; j++)
{
pt1.Y = pt.Y + (int)(tick.TickPoint.Y + ddy);
pt2.Y = pt1.Y;
ddy += dy;
if (pt1.Y >= chartAxis.AxisLineBounds.Y - ScrollOffset.Y &&
pt1.Y < chartAxis.AxisLineBounds.Bottom - ScrollOffset.Y)
{
g.DrawLine(pen, pt1, pt2);
}
}
}
}
#endregion
#endregion
#region Copy/CopyTo
///
/// Creates a copy of the chart element.
///
///
public override ChartVisualElement Copy()
{
MinorTickmarksY copy = new MinorTickmarksY();
CopyTo(copy);
return (copy);
}
///
/// Copies the chart element to the given "copy".
///
///
public override void CopyTo(ChartVisualElement copy)
{
MinorTickmarksY c = copy as MinorTickmarksY;
if (c != null)
{
base.CopyTo(c);
}
}
#endregion
}
#endregion
#region MinorTickmarks
///
/// Represents a Minor tickmark.
///
public class MinorTickmarks : ChartTickmarks
{
#region Private variables
private int _TickmarkCount = 3;
#endregion
public MinorTickmarks(AxisOrientation orientation)
: base(orientation)
{
}
#region Public properties
#region TickmarkCount
///
/// Gets or sets the number of Tickmarks presented between Majortickmarks.
///
[DefaultValue(3), Category("Layout")]
[Description("Indicates the number of Tickmarks presented between Majortickmarks.")]
public int TickmarkCount
{
get { return (_TickmarkCount); }
set
{
if (value != _TickmarkCount)
{
_TickmarkCount = value;
OnPropertyChangedEx("TickmarkCount", VisualChangeType.Layout);
}
}
}
#endregion
#endregion
#region CopyTo
///
/// Copies the chart element to the given "copy".
///
///
public override void CopyTo(ChartVisualElement copy)
{
MinorTickmarks c = copy as MinorTickmarks;
if (c != null)
{
base.CopyTo(c);
c.TickmarkCount = TickmarkCount;
}
}
#endregion
#region GetSerialData
internal override SerialElementCollection GetSerialData(string serialName)
{
SerialElementCollection sec = new SerialElementCollection();
if (serialName != null)
{
if (serialName.Equals("") == true)
serialName = "MinorTickmarks";
sec.AddStartElement(serialName);
}
sec.AddElement(base.GetSerialData(null));
sec.AddValue("TickmarkCount", TickmarkCount, 3);
if (serialName != null)
sec.AddEndElement(serialName);
return (sec);
}
#endregion
#region PutSerialData
#region ProcessValue
internal override void ProcessValue(SerialElement se)
{
switch (se.Name)
{
case "TickmarkCount":
TickmarkCount = int.Parse(se.StringValue);
break;
default:
base.ProcessValue(se);
break;
}
}
#endregion
#endregion
}
#endregion
#endregion
#region ChartTickmarks
[TypeConverter(typeof(BlankExpandableObjectConverter))]
public abstract class ChartTickmarks : ChartVisualElement
{
#region Private variables
private States _States;
private AxisOrientation _AxisOrientation;
private Rectangle _TickmarkBounds;
private TickmarkLayout _TickmarkLayout;
private ChartTickmarkVisualStyle _ChartTickmarkVisualStyle;
private EffectiveStyle _EffectiveStyle;
#endregion
public ChartTickmarks(AxisOrientation orientation)
{
_AxisOrientation = orientation;
InitDefaultStates();
_EffectiveStyle = new EffectiveStyle(this);
Visible = true;
}
#region InitDefaultStates
private void InitDefaultStates()
{
}
#endregion
#region Public properties
#region AxisOrientation
///
/// Gets the axis orientation (X/Y).
///
[Browsable(false)]
[Description("Indicates the axis orientation (X/Y).")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public AxisOrientation AxisOrientation
{
get { return (_AxisOrientation); }
}
#endregion
#region EffectiveStyle
///
/// Gets a reference to the Tickmark's Effective (cached, composite) style.
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("Indicates a reference to the Tickmark's Effective (cached, composite) style.")]
public ChartTickmarkVisualStyle EffectiveStyle
{
get { return (_EffectiveStyle.Style); }
}
#endregion
#region ChartTickmarkVisualStyle
///
/// Gets or sets the visual styles for the Tickmarks.
///
[Category("Style")]
[Description("Indicates the visual styles for the Tickmarks.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ChartTickmarkVisualStyle ChartTickmarkVisualStyle
{
get
{
if (_ChartTickmarkVisualStyle == null)
{
_ChartTickmarkVisualStyle = new ChartTickmarkVisualStyle();
StyleVisualChangeHandler(null, _ChartTickmarkVisualStyle);
}
return (_ChartTickmarkVisualStyle);
}
set
{
if (_ChartTickmarkVisualStyle != value)
{
ChartTickmarkVisualStyle oldValue = _ChartTickmarkVisualStyle;
_ChartTickmarkVisualStyle = value;
OnVisualStyleChanged("ChartTickmarkVisualStyle", oldValue, value);
if (oldValue != null)
oldValue.Dispose();
}
}
}
#endregion
#endregion
#region Internal properties
#region TickmarkBounds
internal Rectangle TickmarkBounds
{
get { return (_TickmarkBounds); }
set { _TickmarkBounds = value; }
}
#endregion
#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)
{
}
#endregion
#region RenderOverride
protected override void RenderOverride(ChartRenderInfo renderInfo)
{
}
#endregion
#region CanRenderTickmarks
protected virtual bool CanRenderTickmarks(ChartTickmarkVisualStyle tstyle)
{
if (Visible == false || tstyle.TickmarkThickness <= 0 || tstyle.TickmarkColor.IsEmpty == true)
return (false);
return (true);
}
#endregion
#region Render
internal override void Render(ChartRenderInfo renderInfo)
{
if (Displayed == true)
RenderOverride(renderInfo);
}
#endregion
#region GetMaxTickmarkLength
internal int GetMaxTickmarkLength(ChartAxis chartAxis, bool inner)
{
int length = (inner == false) ? 4 : 0;
if (Visible == true)
{
ChartTickmarkVisualStyle tstyle = EffectiveStyle;
if (chartAxis.EdgeAxis == false)
{
length = tstyle.TickmarkLength;
}
else
{
switch (tstyle.TickmarkAlignment)
{
case LineAlignment.Near:
if (inner == true)
length = tstyle.TickmarkLength;
break;
case LineAlignment.Center:
length = tstyle.TickmarkLength;
break;
default:
if (inner == false)
length = tstyle.TickmarkLength;
break;
}
}
}
return (length);
}
#endregion
#region GetLocalAdjustedBounds
internal Rectangle GetLocalAdjustedBounds(Rectangle bounds)
{
bounds.Location = GetLocalAdjustedPoint(bounds.Location);
return (bounds);
}
#endregion
#region GetLocalAdjustedPoint
internal Point GetLocalAdjustedPoint(Point pt)
{
ChartAxis axis = Parent as ChartAxis;
ChartXy chartXy = axis.Parent as ChartXy;
if (chartXy != null)
{
pt.X -= ScrollOffset.X;
pt.Y -= ScrollOffset.Y;
if (_AxisOrientation == AxisOrientation.X)
{
pt.X -= chartXy.HScrollOffset;
}
else
{
if (chartXy.VScrollBar.Inverted == true)
pt.Y += chartXy.VScrollOffset;
else
pt.Y -= chartXy.VScrollOffset;
}
}
return (pt);
}
#endregion
#region Style handling
#region ApplyStyles
public override void ApplyStyles(BaseVisualStyle style)
{
ChartTickmarkVisualStyle tstyle = style as ChartTickmarkVisualStyle;
if (tstyle != null)
{
ApplyParentStyles(tstyle, Parent as ChartContainer);
tstyle.ApplyStyle(ChartTickmarkVisualStyle);
if (tstyle.TickmarkColor.IsEmpty == true)
tstyle.TickmarkColor = Color.Gray;
if (tstyle.TickmarkThickness < 0)
tstyle.TickmarkThickness = 1;
if (tstyle.TickmarkLength < 0)
{
if (this is MajorTickmarks)
tstyle.TickmarkLength = 5;
else
tstyle.TickmarkLength = 2;
}
if (tstyle.TickmarkAlignment == LineAlignment.NotSet)
tstyle.TickmarkAlignment = LineAlignment.Far;
}
}
#region ApplyParentStyles
private void ApplyParentStyles(
ChartTickmarkVisualStyle pstyle, ChartContainer item)
{
if (item != null)
{
ApplyParentStyles(pstyle, item.Parent as ChartContainer);
if (item is ChartPanel)
{
pstyle.ApplyStyle(((ChartPanel)item).DefaultVisualStyles.ChartTickmarkVisualStyle);
}
}
else
{
pstyle.ApplyStyle(ChartControl.BaseVisualStyles.ChartTickmarkVisualStyle);
pstyle.ApplyStyle(ChartControl.DefaultVisualStyles.ChartTickmarkVisualStyle);
}
}
#endregion
#endregion
#region InvalidateStyle
///
///Invalidate the cached Style definition
///
public void InvalidateStyle()
{
ClearEffectiveStyles();
}
#endregion
#region ClearEffectiveStyles
protected override void ClearEffectiveStyles()
{
if (_EffectiveStyle.InvalidateStyle() == true)
InvalidateLayout();
}
#endregion
#endregion
#region CopyTo
///
/// Copies the chart element to the given "copy".
///
///
public override void CopyTo(ChartVisualElement copy)
{
ChartTickmarks c = copy as ChartTickmarks;
if (c != null)
{
base.CopyTo(c);
c.ChartTickmarkVisualStyle =
(_ChartTickmarkVisualStyle != null) ? ChartTickmarkVisualStyle.Copy() : null;
}
}
#endregion
#region GetSerialData
internal override SerialElementCollection GetSerialData(string serialName)
{
SerialElementCollection sec = new SerialElementCollection();
if (serialName != null)
{
if (serialName.Equals("") == true)
serialName = "ChartTickmarks";
sec.AddStartElement(serialName);
}
if (_ChartTickmarkVisualStyle != null && _ChartTickmarkVisualStyle.IsEmpty == false)
sec.AddElement(_ChartTickmarkVisualStyle.GetSerialData("ChartTickmarkVisualStyle"));
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 "ChartTickmarkVisualStyle":
sec.PutSerialData(ChartTickmarkVisualStyle);
break;
default:
base.ProcessCollection(se);
break;
}
}
#endregion
#endregion
#region States
[Flags]
protected enum States : uint
{
}
#region TestState
protected bool TestState(States state)
{
return ((_States & state) == state);
}
#endregion
#region SetState
protected void SetState(States state, bool value)
{
if (value == true)
_States |= state;
else
_States &= ~state;
}
#endregion
#endregion
}
#endregion
}