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 }