using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Drawing.Design; using System.Drawing.Drawing2D; using System.Windows.Forms; using DevComponents.Charts.TextMarkup; using DevComponents.DotNetBar.Charts.Style; namespace DevComponents.DotNetBar.Charts { /// /// Represents the collection of ReferenceLines. /// [Editor("DevComponents.Charts.Design.AxisReferenceCollectionEditor, DevComponents.Charts.Design, " + "Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))] public class ReferenceLineCollection : CustomNamedCollection { #region GetUniqueName /// /// Gets a unique (unused) reference line Name. /// /// public string GetUniqueName() { return (GetUniqueName("RefLine")); } #endregion } /// /// Represents a reference line (a vertical or horizontal line on the chart /// that can be used to signify, or reference, a specific axis/chart value). /// public class ReferenceLine : ChartVisualElement, ILegendItem { #region Private variables private States _States; private object _AxisValue; private string _Text; private Size _TextSize; private BodyElement _TextMarkup; private Rectangle _LineBounds; private int _MaxLineCount = 3; private ReferenceLineVisualStyle _ReferenceLineVisualStyle; private EffectiveStyle _EffectiveStyle; private string _LegendText; private ChartLegendItem _LegendItem; private ChartLegendItemVisualStyles _ChartLegendItemVisualStyles; #endregion #region Constructors /// /// ReferenceLine /// public ReferenceLine() { InitDefaultStates(); _EffectiveStyle = new EffectiveStyle(this); } /// /// ReferenceLine /// /// public ReferenceLine(string name) : this() { Name = name; } /// /// ReferenceLine /// /// /// public ReferenceLine(string name, object axisValue) : this(name) { AxisValue = axisValue; } /// /// ReferenceLine /// /// /// public ReferenceLine(string name, object axisValue, string text) : this(name, axisValue) { Text = text; } #endregion #region InitDefaultStates private void InitDefaultStates() { SetState(States.CheckedInLegend, true); SetState(States.ShowInLegend, true); SetState(States.ShowInParentLegend, true); SetState(States.ShowCheckBoxInLegend, true); SetState(States.ShowMarkerInLegend, true); SetState(States.DisplayTextOnTop, true); } #endregion #region Public properties #region AxisValue /// /// Gets or sets the associated axis value of the reference line. /// [DefaultValue(null), Category("Appearance")] [Description("Indicates the associated axis value of the reference line.")] [TypeConverter("DevComponents.Charts.Design.PointValueConverter," + "DevComponents.Charts.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf")] public object AxisValue { get { return (_AxisValue); } set { if (value != _AxisValue) { _AxisValue = value; if (_LegendItem != null) { if (string.IsNullOrEmpty(Name) && string.IsNullOrEmpty(LegendText)) { ChartAxis axis = Parent as ChartAxis; _LegendItem.ItemText = axis.AxisOrientation + "-Axis: " + AxisValue; } } OnPropertyChangedEx("AxisValue", VisualChangeType.Layout); } } } #endregion #region DisplayLineOnTop /// /// Gets or sets whether the reference line is displayed on top of chart data. /// [DefaultValue(false), Category("Appearance")] [Description("Indicates whether the reference line is displayed on top of chart data.")] public bool DisplayLineOnTop { get { return (TestState(States.DisplayLineOnTop)); } set { if (value != DisplayLineOnTop) { SetState(States.DisplayLineOnTop, value); OnPropertyChangedEx("DisplayLineOnTop", VisualChangeType.Render); } } } #endregion #region DisplayTextOnTop /// /// Gets or sets whether the reference text is displayed on top of chart data. /// [DefaultValue(true), Category("Appearance")] [Description("Indicates whether the reference text is displayed on top of chart data.")] public bool DisplayTextOnTop { get { return (TestState(States.DisplayTextOnTop)); } set { if (value != DisplayTextOnTop) { SetState(States.DisplayTextOnTop, value); OnPropertyChangedEx("DisplayTextOnTop", VisualChangeType.Render); } } } #endregion #region EffectiveStyle /// /// Gets a reference to the ReferenceLine's Effective (cached, composite) style. /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public ReferenceLineVisualStyle EffectiveStyle { get { return (_EffectiveStyle.Style); } } #endregion #region EnableTextMarkup /// /// Gets or sets whether text-markup support is enabled for the reference line text /// [DefaultValue(false), Category("Appearance")] [Description("Indicates whether text-markup support is enabled for the reference line text.")] public bool EnableTextMarkup { get { return (TestState(States.EnableTextMarkup)); } set { if (EnableTextMarkup != value) { SetState(States.EnableTextMarkup, value); MarkupTextChanged(); OnPropertyChangedEx("EnableTextMarkup", VisualChangeType.Layout); } } } #region MarkupTextChanged private void MarkupTextChanged() { if (_TextMarkup != null) _TextMarkup.HyperLinkClick -= TextMarkupLinkClick; _TextMarkup = null; if (EnableTextMarkup == true) { if (MarkupParser.IsMarkup(_Text) == true) { _TextMarkup = MarkupParser.Parse(_Text); if (_TextMarkup != null) _TextMarkup.HyperLinkClick += TextMarkupLinkClick; } } } #endregion #region TextMarkupLinkClick /// /// Occurs when a text markup link is clicked /// protected virtual void TextMarkupLinkClick(object sender, EventArgs e) { HyperLink link = sender as HyperLink; if (link != null) ChartControl.DoReferenceLineMarkupLinkClickEvent(this, link); } #endregion #endregion #region InvertVerticalText /// /// Gets or sets whether vertical reference text is inverted. /// [DefaultValue(false), Category("Appearance")] [Description("Indicates whether vertical reference text is inverted.")] public bool InvertVerticalText { get { return (TestState(States.InvertVerticalText)); } set { if (value != InvertVerticalText) { SetState(States.InvertVerticalText, value); OnPropertyChangedEx("InvertVerticalText", VisualChangeType.Render); } } } #endregion #region MaxLineCount /// /// Gets or sets the maximum number of Text lines. /// [DefaultValue(3), Category("Layout")] [Description("Indicates the maximum number of Text lines.")] public int MaxLineCount { get { return (_MaxLineCount); } set { if (value != _MaxLineCount) { _MaxLineCount = value; OnPropertyChangedEx("MaxLineCount", VisualChangeType.Layout); } } } #endregion #region PlainText /// /// Gets text without text-markup (if text-markup is used in Text) /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public string PlainText { get { return (_TextMarkup != null ? _TextMarkup.PlainText : _Text); } } #endregion #region ReferenceLineVisualStyle /// /// Gets or sets the visual style for the ReferenceLine. /// [Category("Style")] [Description("Indicates the visual style for the ReferenceLine.")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public ReferenceLineVisualStyle ReferenceLineVisualStyle { get { if (_ReferenceLineVisualStyle == null) { _ReferenceLineVisualStyle = new ReferenceLineVisualStyle(); StyleVisualChangeHandler(null, _ReferenceLineVisualStyle); } return (_ReferenceLineVisualStyle); } set { if (_ReferenceLineVisualStyle != value) { ReferenceLineVisualStyle oldValue = _ReferenceLineVisualStyle; _ReferenceLineVisualStyle = value; OnVisualStyleChanged("ReferenceLineVisualStyle", oldValue, value); if (oldValue != null) oldValue.Dispose(); } } } #endregion #region Text /// /// Gets or sets the ReferenceLine Text. /// [DefaultValue(null), Category("Layout")] [Description("Indicates the ReferenceLine Text.")] public string Text { get { return (_Text); } set { if (value != _Text) { _Text = value; MarkupTextChanged(); OnPropertyChangedEx("Text", VisualChangeType.Layout); } } } #endregion #endregion #region Internal properties #region LineBounds internal Rectangle LineBounds { get { if (_LineBounds.IsEmpty == true) _LineBounds = GetLineBounds(); return (_LineBounds); } set { _LineBounds = value; } } #endregion #region TextMarkup internal BodyElement TextMarkup { get { return (_TextMarkup); } } #endregion #endregion #region MeasureOverride protected override void MeasureOverride(ChartLayoutInfo layoutInfo) { _TextSize = Size.Empty; } #region MeasureText private Size MeasureText(Graphics g, ReferenceLineVisualStyle style, Size vsize) { Size size = Size.Empty; string s = Text; if (string.IsNullOrEmpty(s) == false) { if (TextMarkup != null) { size = GetMarkupTextSize(g, TextMarkup, style, (vsize.Width > 0 ? vsize.Width : 10000)); } else { using (StringFormat sf = new StringFormat()) { style.GetStringFormatFlags(sf); if (MaxLineCount <= 1) sf.FormatFlags |= StringFormatFlags.NoWrap; size = g.MeasureString(Text, style.Font, vsize, sf).ToSize(); } } size.Width++; size.Height++; if (MaxLineCount > 1) { int lineHeight = (int)(Math.Ceiling(style.Font.GetHeight())) * MaxLineCount; if (size.Height > lineHeight) size.Height = lineHeight; } } return (size); } #region GetMarkupTextSize private Size GetMarkupTextSize(Graphics g, BodyElement textMarkup, ReferenceLineVisualStyle style, int width) { MarkupDrawContext d = new MarkupDrawContext(g, style.Font, style.TextColor, false); textMarkup.InvalidateElementsSize(); textMarkup.Measure(new Size(width, 0), d); return (textMarkup.Bounds.Size); } #endregion #endregion #endregion #region ArrangeOverride protected override void ArrangeOverride(ChartLayoutInfo layoutInfo) { LineBounds = Rectangle.Empty; ChartAxis axis = Parent as ChartAxis; if (axis != null) { ChartXy chartXy = axis.Parent as ChartXy; if (chartXy != null) { Rectangle bounds = chartXy.ContentBounds; if (chartXy.HScrollBar.Enabled == true) bounds.Height -= (chartXy.HScrollBar.Height); if (chartXy.VScrollBar.Enabled == true) bounds.Width -= (chartXy.VScrollBar.Width); BoundsRelative = GetLineBoundsEx(); } } } #endregion #region RenderOverride protected override void RenderOverride(ChartRenderInfo renderInfo) { } #region RenderLine internal void RenderLine(ChartRenderInfo renderInfo) { ChartAxis axis = Parent as ChartAxis; if (axis != null) { Graphics g = renderInfo.Graphics; ChartXy chartXy = axis.Parent as ChartXy; Rectangle contentBounds = chartXy.ContentBounds; ReferenceLineVisualStyle rstyle = EffectiveStyle; if (axis.AxisOrientation == AxisOrientation.X) RenderLineX(g, contentBounds, rstyle); else RenderLineY(g, contentBounds, rstyle); } } #region RenderLineX private void RenderLineX(Graphics g, Rectangle contentBounds, ReferenceLineVisualStyle rstyle) { if (rstyle.LinePattern != LinePattern.None) { Rectangle lbounds = LineBounds; if (lbounds.X > contentBounds.X && lbounds.X < contentBounds.Right) { Point pt1 = lbounds.Location; Point pt2 = new Point(pt1.X, lbounds.Bottom); using (Pen pen = new Pen(rstyle.LineColor, Dpi.Width(rstyle.LineWidth))) { if (rstyle.LinePattern != LinePattern.NotSet) pen.DashStyle = (DashStyle)rstyle.LinePattern; g.DrawLine(pen, pt2, pt1); } } } } #endregion #region RenderLineY private void RenderLineY(Graphics g, Rectangle contentBounds, ReferenceLineVisualStyle rstyle) { if (rstyle.LinePattern != LinePattern.None) { Rectangle lbounds = LineBounds; if (lbounds.Y > contentBounds.Y && lbounds.Y < contentBounds.Bottom) { Point pt1 = lbounds.Location; Point pt2 = new Point(lbounds.Right, pt1.Y); using (Pen pen = new Pen(rstyle.LineColor, Dpi.Height(rstyle.LineWidth))) { if (rstyle.LinePattern != LinePattern.NotSet) pen.DashStyle = (DashStyle)rstyle.LinePattern; g.DrawLine(pen, pt1, pt2); } } } } #endregion #endregion #region RenderLineText internal void RenderLineText(ChartRenderInfo renderInfo) { ChartAxis axis = Parent as ChartAxis; if (axis != null) { Graphics g = renderInfo.Graphics; ChartXy chartXy = axis.Parent as ChartXy; Rectangle bounds = chartXy.ContentBounds; if (chartXy.HScrollBar.Enabled == true) bounds.Height -= (chartXy.HScrollBar.Height + 1); if (chartXy.VScrollBar.Enabled == true) bounds.Width -= (chartXy.VScrollBar.Width + 1); ReferenceLineVisualStyle rstyle = EffectiveStyle; if (axis.AxisOrientation == AxisOrientation.X) RenderTextX(g, bounds, rstyle); else RenderTextY(g, bounds, rstyle); } } #region RenderTextX private void RenderTextX(Graphics g, Rectangle bounds, ReferenceLineVisualStyle rstyle) { Rectangle lbounds = LineBounds; if (lbounds.X > bounds.X && lbounds.X < bounds.Right) { if (_TextSize == Size.Empty) { Rectangle r = bounds; int n = r.Width; r.Width = r.Height; r.Height = n; if (rstyle.AllowWrap == Tbool.False) r.Size = Size.Empty; _TextSize = MeasureText(g, rstyle, r.Size); } int dy = (lbounds.Y + lbounds.Bottom) / 2; Point pt = new Point(lbounds.X, dy); int rotDegrees = (InvertVerticalText == true) ? 90 : -90; g.TranslateTransform(pt.X, pt.Y); g.RotateTransform(rotDegrees); Rectangle tbounds = new Rectangle( -bounds.Height / 2, -rstyle.LineWidth / 2, bounds.Height, rstyle.LineWidth); switch (rstyle.TextAlignment) { case Alignment.TopLeft: case Alignment.TopCenter: case Alignment.TopRight: tbounds.Y -= (_TextSize.Height + rstyle.TextPadding.Bottom); break; case Alignment.MiddleLeft: case Alignment.MiddleCenter: case Alignment.MiddleRight: tbounds.Y -= (_TextSize.Height - tbounds.Height) / 2 + (rstyle.TextPadding.Vertical / 2 - rstyle.TextPadding.Top); break; case Alignment.BottomLeft: case Alignment.BottomCenter: case Alignment.BottomRight: tbounds.Y += (rstyle.LineWidth + rstyle.TextPadding.Top); break; } switch (rstyle.TextAlignment) { case Alignment.TopRight: case Alignment.MiddleRight: case Alignment.BottomRight: tbounds.X = (tbounds.Right - _TextSize.Width); tbounds.Width = _TextSize.Width; break; } tbounds.X += +rstyle.TextPadding.Left; tbounds.Width -= rstyle.TextPadding.Horizontal; tbounds.Height = _TextSize.Height; RenderText(g, tbounds, rstyle); g.ResetTransform(); } } #endregion #region RenderTextY private void RenderTextY(Graphics g, Rectangle bounds, ReferenceLineVisualStyle rstyle) { Rectangle lbounds = LineBounds; if (lbounds.Y > bounds.Y && lbounds.Y < bounds.Bottom) { if (_TextSize == Size.Empty) { Rectangle r = bounds; if (rstyle.AllowWrap == Tbool.False) r.Size = Size.Empty; _TextSize = MeasureText(g, rstyle, r.Size); } Point pt1 = lbounds.Location; Point pt2 = new Point(lbounds.Right, pt1.Y); Rectangle tbounds = new Rectangle(pt1.X, pt1.Y, pt2.X - pt1.X, 0); switch (rstyle.TextAlignment) { case Alignment.TopLeft: case Alignment.TopCenter: case Alignment.TopRight: tbounds.Y -= ((rstyle.LineWidth / 2) + rstyle.TextPadding.Bottom + _TextSize.Height); break; case Alignment.MiddleLeft: case Alignment.MiddleCenter: case Alignment.MiddleRight: tbounds.Y -= ((_TextSize.Height + rstyle.TextPadding.Vertical) / 2 - rstyle.TextPadding.Top); break; case Alignment.BottomLeft: case Alignment.BottomCenter: case Alignment.BottomRight: tbounds.Y += ((rstyle.LineWidth / 2) + rstyle.TextPadding.Top); break; } switch (rstyle.TextAlignment) { case Alignment.TopRight: case Alignment.MiddleRight: case Alignment.BottomRight: tbounds.X = (tbounds.Right - _TextSize.Width - rstyle.TextPadding.Horizontal); tbounds.Width = _TextSize.Width + rstyle.TextPadding.Horizontal; break; } tbounds.X += rstyle.TextPadding.Left; tbounds.Width -= rstyle.TextPadding.Horizontal; tbounds.Height += _TextSize.Height; RenderText(g, tbounds, rstyle); } } #endregion #region RenderText private void RenderText( Graphics g, Rectangle r, ReferenceLineVisualStyle style) { if (r.Width > 0 && r.Height > 0) { string s = Text; if (string.IsNullOrEmpty(s) == false) { if (TextMarkup != null) { RenderTextMarkup(g, r, style); } else { using (SolidBrush br = new SolidBrush(style.TextColor)) { using (StringFormat sf = new StringFormat()) { style.GetStringFormatFlags(sf); g.DrawString(Text, style.Font, br, r, sf); } } } } } } #region RenderTextMarkup private void RenderTextMarkup( Graphics g, Rectangle r, ReferenceLineVisualStyle style) { MarkupDrawContext d = new MarkupDrawContext(g, style.Font, style.TextColor, false); TextMarkup.Arrange(r, d); Size size = TextMarkup.Bounds.Size; TextMarkup.Bounds = new Rectangle(r.Location, size); Region oldClip = g.Clip; try { g.SetClip(r, CombineMode.Intersect); TextMarkup.Render(d); } finally { g.Clip = oldClip; } } #endregion #endregion #endregion #endregion #region GetLineBounds private Rectangle GetLineBounds() { ChartAxis axis = Parent as ChartAxis; if (axis != null) { ChartXy chartXy = axis.Parent as ChartXy; if (chartXy != null) { Rectangle bounds = chartXy.ContentBounds; if (chartXy.HScrollBar.Enabled == true) bounds.Height -= (chartXy.HScrollBar.Height); if (chartXy.VScrollBar.Enabled == true) bounds.Width -= (chartXy.VScrollBar.Width); Point pt; if (axis.AxisOrientation == AxisOrientation.X) { pt = new Point(axis.GetDisplayValue(AxisValue), bounds.Y); pt = chartXy.GetLocalAdjustedPoint(pt); pt.Y = bounds.Y; } else { pt = new Point(bounds.X, axis.GetDisplayValue(AxisValue)); pt = chartXy.GetLocalAdjustedPoint(pt); pt.X = bounds.X; } return (new Rectangle(pt, bounds.Size)); } } return (Rectangle.Empty); } #endregion #region GetLineBoundsEx private Rectangle GetLineBoundsEx() { ChartAxis axis = Parent as ChartAxis; if (axis != null) { ChartXy chartXy = axis.Parent as ChartXy; if (chartXy != null) { Rectangle bounds = chartXy.ContentBounds; if (chartXy.HScrollBar.Enabled == true) bounds.Height -= (chartXy.HScrollBar.Height); if (chartXy.VScrollBar.Enabled == true) bounds.Width -= (chartXy.VScrollBar.Width); Point pt; if (axis.AxisOrientation == AxisOrientation.X) pt = new Point(axis.GetDisplayValue(AxisValue), bounds.Y); else pt = new Point(bounds.X, axis.GetDisplayValue(AxisValue)); return (new Rectangle(pt, bounds.Size)); } } return (Rectangle.Empty); } #endregion #region GetDoubleValue private double GetDoubleValue(object value) { if (value is double) return (double)value; return (Convert.ToDouble(value)); } #endregion #region EnsureVisible /// /// Ensures that the reference line is visible on screen. /// public void EnsureVisible() { EnsureVisible(false); } /// /// Ensures that the reference line is visible on screen, and /// optionally centered (if possible). /// /// public void EnsureVisible(bool center) { ChartAxis axis = Parent as ChartAxis; if (axis != null) axis.EnsureVisible(AxisValue, center); } #endregion #region Style handling #region ApplyStyles public override void ApplyStyles(BaseVisualStyle style) { ReferenceLineVisualStyle rstyle = style as ReferenceLineVisualStyle; if (rstyle != null) { ApplyParentStyles(rstyle, Parent as ChartContainer); rstyle.ApplyStyle(ReferenceLineVisualStyle); if (rstyle.LineColor.IsEmpty == true) rstyle.LineColor = Color.Red; if (rstyle.LineWidth < 0) rstyle.LineWidth = 1; if (rstyle.Font == null) rstyle.Font = SystemFonts.DefaultFont; if (rstyle.TextColor.IsEmpty == true) rstyle.TextColor = Color.Black; } } #region ApplyParentStyles private void ApplyParentStyles( ReferenceLineVisualStyle pstyle, ChartContainer item) { if (item != null) { ApplyParentStyles(pstyle, item.Parent as ChartContainer); ChartPanel cp = item as ChartPanel; if (cp != null) pstyle.ApplyStyle(cp.DefaultVisualStyles.ReferenceLineVisualStyle); } else { pstyle.ApplyStyle(ChartControl.BaseVisualStyles.ReferenceLineVisualStyle); pstyle.ApplyStyle(ChartControl.DefaultVisualStyles.ReferenceLineVisualStyle); } } #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(); if (LegendItem != null) LegendItem.EffectiveStyles.InvalidateStyles(); } #endregion #region StyleChanged protected override void StyleChanged(object sender, PropertyChangedEventArgs e) { base.StyleChanged(sender, e); if (sender is ChartLegendItemVisualStyles && LegendItem != null) InvalidateRender(LegendItem.Bounds); } #endregion #endregion #region ILegendItem #region ChartLegendItemVisualStyles /// /// Gets or sets the visual styles for the Legend item. /// [Category("Style")] [Description("Indicates the visual styles for the Legend item.")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public ChartLegendItemVisualStyles ChartLegendItemVisualStyles { get { if (_ChartLegendItemVisualStyles == null) { _ChartLegendItemVisualStyles = new ChartLegendItemVisualStyles(); StyleVisualChangeHandler(null, _ChartLegendItemVisualStyles); } return (_ChartLegendItemVisualStyles); } set { if (_ChartLegendItemVisualStyles != value) { ChartLegendItemVisualStyles oldValue = _ChartLegendItemVisualStyles; _ChartLegendItemVisualStyles = value; OnStyleChanged("ChartLegendItemVisualStyles", oldValue, value); if (oldValue != null) oldValue.Dispose(); } } } #endregion #region CheckedInLegend /// /// Gets or sets whether the ReferenceLine is checked in the Legend. /// [DefaultValue(true), Category("Appearance")] [Description("Indicates whether the ReferenceLine is checked in the Legend.")] public bool CheckedInLegend { get { return (TestState(States.CheckedInLegend)); } set { if (value != CheckedInLegend) { SetState(States.CheckedInLegend, value); if (LegendItem != null) LegendItem.UpdateCheckState(); OnPropertyChangedEx("CheckedInLegend", VisualChangeType.Render); } } } #endregion #region ShowCheckBoxInLegend /// /// Gets or sets whether a checkbox for the ReferenceLine is shown in the Legend. /// [DefaultValue(true), Category("Appearance")] [Description("Indicates whether a checkbox for the ReferenceLine is shown in the Legend.")] public bool ShowCheckBoxInLegend { get { return (TestState(States.ShowCheckBoxInLegend)); } set { if (value != ShowCheckBoxInLegend) { SetState(States.ShowCheckBoxInLegend, value); OnPropertyChangedEx("ShowCheckBoxInLegend", VisualChangeType.Layout); } } } #endregion #region ShowInLegend /// /// Gets or sets whether the ReferenceLine is shown in the Legend. /// [DefaultValue(true), Category("Appearance")] [Description("Indicates whether the ReferenceLine is shown in the Legend.")] public bool ShowInLegend { get { return (TestState(States.ShowInLegend)); } set { if (value != ShowInLegend) { SetState(States.ShowInLegend, value); OnPropertyChangedEx("ShowInLegend", VisualChangeType.Layout); } } } #endregion #region ShowInParentLegend /// /// Gets or sets whether the Reference Line is shown in parent Legend(s). /// [DefaultValue(true), Category("Appearance")] [Description("Indicates whether the Reference Line is shown in parent Legend(s).")] public bool ShowInParentLegend { get { return (TestState(States.ShowInParentLegend)); } set { if (value != ShowInParentLegend) { SetState(States.ShowInParentLegend, value); OnPropertyChangedEx("ShowInParentLegend", VisualChangeType.Layout); } } } #endregion #region ShowMarkerInLegend /// /// Gets or sets whether the ReferenceLine Marker is shown in the Legend. /// [DefaultValue(true), Category("Appearance")] [Description("Indicates whether the ReferenceLine Marker is shown in the Legend.")] public bool ShowMarkerInLegend { get { return (TestState(States.ShowMarkerInLegend)); } set { if (value != ShowMarkerInLegend) { SetState(States.ShowMarkerInLegend, value); OnPropertyChangedEx("ShowMarkerInLegend", VisualChangeType.Layout); } } } #endregion #region LegendItem /// /// Gets the item's parent LegendItem. /// [Description("Indicates the item's parent LegendItem.")] [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public ChartLegendItem LegendItem { get { return (_LegendItem); } internal set { _LegendItem = value; } } #endregion #region LegendText /// /// Gets or sets the text to display in the legend. /// [DefaultValue(null), Category("DataLabel")] [Description("Indicates the text to display in the legend.")] public string LegendText { get { return (_LegendText); } set { if (value != _LegendText) { _LegendText = value; OnPropertyChangedEx("LegendText", Style.VisualChangeType.Layout); } } } #endregion #region GetLegendItem public ChartLegendItem GetLegendItem() { _LegendItem = null; if (ShowInLegend == true) { _LegendItem = new ChartLegendItem(); if (CheckedInLegend == true) _LegendItem.CheckState = CheckState.Checked; _LegendItem.Name = Name; _LegendItem.ItemText = LegendText; if (string.IsNullOrEmpty(_LegendItem.Name) == true) _LegendItem.Name = "(RefLine)"; _LegendItem.ChartItems.Add(this); } return (_LegendItem); } #endregion #region GetLegendItems public List GetLegendItems() { List list = null; ChartLegendItem item = GetLegendItem(); if (item != null) { list = new List(1); list.Add(item); } return (list); } #endregion #region GetLegendItemColor public Color GetLegendItemColor() { ReferenceLineVisualStyle rstyle = EffectiveStyle; return (rstyle.LineColor); } #endregion #region RenderLegendItemMarker public void RenderLegendItemMarker(Graphics g, ChartLegendItem litem, ChartLegendItemVisualStyle style) { ReferenceLineVisualStyle rstyle = EffectiveStyle; if (rstyle.LinePattern != LinePattern.None) { Rectangle bounds = litem.MarkerBounds; int n = bounds.Height / 2; int lineWidth = Math.Min(rstyle.LineWidth, bounds.Height); using (Pen pen = new Pen(GetLegendItemColor(), lineWidth)) { if (rstyle.LinePattern != LinePattern.NotSet) pen.DashStyle = (DashStyle)rstyle.LinePattern; g.DrawLine(pen, new Point(bounds.X, bounds.Y + n), new Point(bounds.Right - 1, bounds.Y + n)); } } } #endregion #endregion #region Copy/CopyTo public override ChartVisualElement Copy() { ReferenceLine copy = new ReferenceLine(); CopyTo(copy); return (copy); } public override void CopyTo(ChartVisualElement copy) { ReferenceLine c = copy as ReferenceLine; if (c != null) { base.CopyTo(c); c.AxisValue = AxisValue; c.DisplayLineOnTop = DisplayLineOnTop; c.DisplayTextOnTop = DisplayTextOnTop; c.EnableTextMarkup = EnableTextMarkup; c.InvertVerticalText = InvertVerticalText; c.MaxLineCount = MaxLineCount; c.ReferenceLineVisualStyle = (_ReferenceLineVisualStyle != null) ? ReferenceLineVisualStyle.Copy() : null; c.Text = Text; c.CheckedInLegend = CheckedInLegend; c.LegendText = LegendText; c.ShowCheckBoxInLegend = ShowCheckBoxInLegend; c.ShowInLegend = ShowInLegend; c.ShowInParentLegend = ShowInParentLegend; c.ShowMarkerInLegend = ShowMarkerInLegend; } } #endregion #region GetSerialData internal override SerialElementCollection GetSerialData(string serialName) { SerialElementCollection sec = new SerialElementCollection(); if (serialName != null) { if (serialName.Equals("") == true) serialName = "ReferenceLine"; sec.AddStartElement(serialName); } sec.AddValue("AxisValue", AxisValue, null); sec.AddValue("DisplayLineOnTop", DisplayLineOnTop, false); sec.AddValue("DisplayTextOnTop", DisplayTextOnTop, true); sec.AddValue("EnableTextMarkup", EnableTextMarkup, false); sec.AddValue("InvertVerticalText", InvertVerticalText, false); sec.AddValue("MaxLineCount", MaxLineCount, 3); if (_ReferenceLineVisualStyle != null && _ReferenceLineVisualStyle.IsEmpty == false) sec.AddElement(_ReferenceLineVisualStyle.GetSerialData("ReferenceLineVisualStyle")); sec.AddValue("Text", Text, null); sec.AddValue("CheckedInLegend", CheckedInLegend, true); sec.AddValue("LegendText", LegendText, null); sec.AddValue("ShowCheckBoxInLegend", ShowCheckBoxInLegend, true); sec.AddValue("ShowInLegend", ShowInLegend, true); sec.AddValue("ShowInParentLegend", ShowInParentLegend, true); sec.AddValue("ShowMarkerInLegend", ShowMarkerInLegend, true); sec.AddElement(base.GetSerialData(null)); if (serialName != null) sec.AddEndElement(serialName); return (sec); } #endregion #region PutSerialData #region ProcessValue internal override void ProcessValue(SerialElement se) { switch (se.Name) { case "AxisValue": AxisValue = se.DataValue; break; case "CheckedInLegend": CheckedInLegend = bool.Parse(se.StringValue); break; case "DisplayLineOnTop": DisplayLineOnTop = bool.Parse(se.StringValue); break; case "DisplayTextOnTop": DisplayTextOnTop = bool.Parse(se.StringValue); break; case "EnableTextMarkup": EnableTextMarkup = bool.Parse(se.StringValue); break; case "InvertVerticalText": InvertVerticalText = bool.Parse(se.StringValue); break; case "LegendText": LegendText = se.StringValue; break; case "MaxLineCount": MaxLineCount = int.Parse(se.StringValue); break; case "ShowCheckBoxInLegend": ShowCheckBoxInLegend = bool.Parse(se.StringValue); break; case "ShowInLegend": ShowInLegend = bool.Parse(se.StringValue); break; case "ShowInParentLegend": ShowInParentLegend = bool.Parse(se.StringValue); break; case "ShowMarkerInLegend": ShowMarkerInLegend = bool.Parse(se.StringValue); break; case "Text": Text = 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 "ReferenceLineVisualStyle": sec.PutSerialData(ReferenceLineVisualStyle); break; default: base.ProcessCollection(se); break; } } #endregion #endregion #region States [Flags] private enum States : uint { CheckedInLegend = (1U << 1), ShowCheckBoxInLegend = (1U << 2), ShowInLegend = (1U << 3), ShowInParentLegend = (1U << 4), ShowMarkerInLegend = (1U << 5), DisplayLineOnTop = (1U << 6), DisplayTextOnTop = (1U << 7), EnableTextMarkup = (1U << 8), InvertVerticalText = (1U << 9) } #region TestState private bool TestState(States state) { return ((_States & state) == state); } #endregion #region SetState private void SetState(States state, bool value) { if (value == true) _States |= state; else _States &= ~state; } #endregion #endregion #region IDisposable public override void Dispose() { ChartLegendItemVisualStyles = null; ReferenceLineVisualStyle = null; base.Dispose(); } #endregion } }