//------------------------------------------------------------- // // Copyright © Microsoft Corporation. All Rights Reserved. // //------------------------------------------------------------- // @owner=alexgor, deliant //================================================================= // File: LineAnnotation.cs // // Namespace: System.Web.UI.WebControls[Windows.Forms].Charting // // Classes: LineAnnotation, VerticalLineAnnotation, // HorizontalLineAnnotation // // Purpose: Line annotation class. // // Reviewed: // //=================================================================== #region Used namespace using System; using System.Collections; using System.Collections.Specialized; using System.ComponentModel; using System.ComponentModel.Design; using System.Data; using System.Drawing; using System.Drawing.Design; using System.Drawing.Text; using System.Drawing.Drawing2D; #if Microsoft_CONTROL using System.Windows.Forms.DataVisualization.Charting; using System.Windows.Forms.DataVisualization.Charting.Data; using System.Windows.Forms.DataVisualization.Charting.ChartTypes; using System.Windows.Forms.DataVisualization.Charting.Utilities; using System.Windows.Forms.DataVisualization.Charting.Borders3D; #else using System.Web; using System.Web.UI; using System.Web.UI.DataVisualization.Charting; using System.Web.UI.DataVisualization.Charting.Data; using System.Web.UI.DataVisualization.Charting.Utilities; #endif #endregion #if Microsoft_CONTROL namespace System.Windows.Forms.DataVisualization.Charting #else namespace System.Web.UI.DataVisualization.Charting #endif { /// /// LineAnnotation is a class that represents a line annotation. /// [ SRDescription("DescriptionAttributeLineAnnotation_LineAnnotation"), ] #if ASPPERM_35 [AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)] #endif public class LineAnnotation : Annotation { #region Fields // Indicates that an infinitive line should be drawn through 2 specified points. private bool _isInfinitive = false; // Line start/end caps private LineAnchorCapStyle _startCap = LineAnchorCapStyle.None; private LineAnchorCapStyle _endCap = LineAnchorCapStyle.None; #endregion #region Construction and Initialization /// /// Default public constructor. /// public LineAnnotation() : base() { this.anchorAlignment = ContentAlignment.TopLeft; } #endregion #region Properties #region Line Visual Attributes /// /// Gets or sets a flag that indicates if an infinitive line should be drawn. /// /// /// True if a line should be drawn infinitively through 2 points provided, false otherwise. /// [ SRCategory("CategoryAttributeAppearance"), DefaultValue(false), SRDescription("DescriptionAttributeDrawInfinitive"), ] virtual public bool IsInfinitive { get { return _isInfinitive; } set { _isInfinitive = value; Invalidate(); } } /// /// Gets or sets a cap style used at the start of an annotation line. /// /// /// /// A value, used for a cap style used at the start of an annotation line. /// [ SRCategory("CategoryAttributeAppearance"), DefaultValue(LineAnchorCapStyle.None), SRDescription("DescriptionAttributeStartCap3"), ] virtual public LineAnchorCapStyle StartCap { get { return _startCap; } set { _startCap = value; Invalidate(); } } /// /// Gets or sets a cap style used at the end of an annotation line. /// /// /// /// A value, used for a cap style used at the end of an annotation line. /// [ SRCategory("CategoryAttributeAppearance"), DefaultValue(LineAnchorCapStyle.None), SRDescription("DescriptionAttributeStartCap3"), ] virtual public LineAnchorCapStyle EndCap { get { return _endCap; } set { _endCap = value; Invalidate(); } } #endregion #region Non Applicable Annotation Appearance Attributes (set as Non-Browsable) /// /// Not applicable to this annotation type. /// /// /// A value. /// [ SRCategory("CategoryAttributeAppearance"), Browsable(false), DefaultValue(typeof(ContentAlignment), "MiddleCenter"), ] override public ContentAlignment Alignment { get { return base.Alignment; } set { base.Alignment = value; } } /// /// Gets or sets an annotation's text style. /// /// /// /// /// A value used to draw an annotation's text. /// [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] public override TextStyle TextStyle { get { return base.TextStyle; } set { base.TextStyle = value; } } /// /// Not applicable to this annotation type. /// /// /// /// A value. /// [ SRCategory("CategoryAttributeAppearance"), Browsable(false), DefaultValue(typeof(Color), "Black"), SRDescription("DescriptionAttributeForeColor"), TypeConverter(typeof(ColorConverter)), Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base) ] override public Color ForeColor { get { return base.ForeColor; } set { base.ForeColor = value; } } /// /// Not applicable to this annotation type. /// /// /// /// A object. /// [ SRCategory("CategoryAttributeAppearance"), Browsable(false), DefaultValue(typeof(Font), "Microsoft Sans Serif, 8pt"), ] override public Font Font { get { return base.Font; } set { base.Font = value; } } /// /// Not applicable to this annotation type. /// [ SRCategory("CategoryAttributeAppearance"), Browsable(false), DefaultValue(typeof(Color), ""), NotifyParentPropertyAttribute(true), TypeConverter(typeof(ColorConverter)), Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base) ] override public Color BackColor { get { return base.BackColor; } set { base.BackColor = value; } } /// /// Not applicable to this annotation type. /// /// /// A value. /// [ SRCategory("CategoryAttributeAppearance"), Browsable(false), DefaultValue(ChartHatchStyle.None), NotifyParentPropertyAttribute(true), Editor(Editors.HatchStyleEditor.Editor, Editors.HatchStyleEditor.Base) ] override public ChartHatchStyle BackHatchStyle { get { return base.BackHatchStyle; } set { base.BackHatchStyle = value; } } /// /// Not applicable to this annotation type. /// [ SRCategory("CategoryAttributeAppearance"), Browsable(false), DefaultValue(GradientStyle.None), NotifyParentPropertyAttribute(true), Editor(Editors.GradientEditor.Editor, Editors.GradientEditor.Base) ] override public GradientStyle BackGradientStyle { get { return base.BackGradientStyle; } set { base.BackGradientStyle = value; } } /// /// Not applicable to this annotation type. /// [ SRCategory("CategoryAttributeAppearance"), Browsable(false), DefaultValue(typeof(Color), ""), NotifyParentPropertyAttribute(true), TypeConverter(typeof(ColorConverter)), Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base) ] override public Color BackSecondaryColor { get { return base.BackSecondaryColor; } set { base.BackSecondaryColor = value; } } #endregion #region Position /// /// Gets or sets a flag that specifies whether the size of an annotation is always /// defined in relative chart coordinates. /// /// /// /// /// True if an annotation's and are always /// in chart relative coordinates, false otherwise. /// /// /// An annotation's width and height may be set in relative chart or axes coordinates. /// By default, relative chart coordinates are used. /// /// To use axes coordinates for size set the IsSizeAlwaysRelative property to /// false and either anchor the annotation to a data point or set the /// or properties. /// /// [ SRCategory("CategoryAttributePosition"), DefaultValue(true), SRDescription("DescriptionAttributeSizeAlwaysRelative3"), ] override public bool IsSizeAlwaysRelative { get { return base.IsSizeAlwaysRelative; } set { base.IsSizeAlwaysRelative = value; } } #endregion // Position #region Anchor /// /// Gets or sets an annotation position's alignment to the anchor point. /// /// /// /// /// /// /// /// A value that represents the annotation's alignment to /// the anchor point. /// /// /// The annotation must be anchored using either , or the /// and properties. Its and /// properties must be set to Double.NaN. /// [ SRCategory("CategoryAttributeAnchor"), Browsable(false), EditorBrowsableAttribute(EditorBrowsableState.Never), DefaultValue(typeof(ContentAlignment), "TopLeft"), SRDescription("DescriptionAttributeAnchorAlignment"), ] override public ContentAlignment AnchorAlignment { get { return base.AnchorAlignment; } set { base.AnchorAlignment = value; } } #endregion // Anchoring #region Other /// /// Gets or sets an annotation's type name. /// /// /// This property is used to get the name of each annotation type /// (e.g. Line, Rectangle, Ellipse). /// /// This property is for internal use and is hidden at design and run time. /// /// [ SRCategory("CategoryAttributeMisc"), Bindable(true), Browsable(false), EditorBrowsableAttribute(EditorBrowsableState.Never), DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden), SerializationVisibilityAttribute(SerializationVisibility.Hidden), SRDescription("DescriptionAttributeAnnotationType"), ] public override string AnnotationType { get { return "Line"; } } /// /// Gets or sets an annotation's selection points style. /// /// /// A value that represents the annotation /// selection style. /// /// /// This property is for internal use and is hidden at design and run time. /// [ SRCategory("CategoryAttributeAppearance"), DefaultValue(SelectionPointsStyle.Rectangle), ParenthesizePropertyNameAttribute(true), Browsable(false), EditorBrowsableAttribute(EditorBrowsableState.Never), DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden), SerializationVisibilityAttribute(SerializationVisibility.Hidden), SRDescription("DescriptionAttributeSelectionPointsStyle"), ] override internal SelectionPointsStyle SelectionPointsStyle { get { return SelectionPointsStyle.TwoPoints; } } #endregion #endregion #region Methods /// /// Adjusts the two coordinates of the line. /// /// First line coordinate. /// Second line coordinate. /// Selection rectangle. virtual internal void AdjustLineCoordinates(ref PointF point1, ref PointF point2, ref RectangleF selectionRect) { // Adjust line points to draw infinitive line if(IsInfinitive) { if(Math.Round(point1.X , 3) == Math.Round(point2.X, 3)) { point1.Y = (point1.Y < point2.Y) ? 0f : 100f; point2.Y = (point1.Y < point2.Y) ? 100f : 0f; } else if(Math.Round(point1.Y , 3) == Math.Round(point2.Y, 3)) { point1.X = (point1.X < point2.X) ? 0f : 100f; point2.X = (point1.X < point2.X) ? 100f : 0f; } else { // Calculate intersection point of the line with two bounaries Y = 0 and Y = 100 PointF intersectionPoint1 = PointF.Empty; intersectionPoint1.Y = 0f; intersectionPoint1.X = (0f - point1.Y) * (point2.X - point1.X) / (point2.Y - point1.Y) + point1.X; PointF intersectionPoint2 = PointF.Empty; intersectionPoint2.Y = 100f; intersectionPoint2.X = (100f - point1.Y) * (point2.X - point1.X) / (point2.Y - point1.Y) + point1.X; // Select point closect to the intersection point1 = (point1.Y < point2.Y) ? intersectionPoint1 : intersectionPoint2; point2 = (point1.Y < point2.Y) ? intersectionPoint2 : intersectionPoint1; } } } /// /// Paints an annotation object on the specified graphics. /// /// /// A object, used to paint an annotation object. /// /// /// Reference to the owner control. /// override internal void Paint(Chart chart, ChartGraphics graphics) { // Get annotation position in relative coordinates PointF firstPoint = PointF.Empty; PointF anchorPoint = PointF.Empty; SizeF size = SizeF.Empty; GetRelativePosition(out firstPoint, out size, out anchorPoint); PointF secondPoint = new PointF(firstPoint.X + size.Width, firstPoint.Y + size.Height); // Create selection rectangle RectangleF selectionRect = new RectangleF(firstPoint, new SizeF(secondPoint.X - firstPoint.X, secondPoint.Y - firstPoint.Y)); // Adjust coordinates AdjustLineCoordinates(ref firstPoint, ref secondPoint, ref selectionRect); // Check if text position is valid if( float.IsNaN(firstPoint.X) || float.IsNaN(firstPoint.Y) || float.IsNaN(secondPoint.X) || float.IsNaN(secondPoint.Y) ) { return; } // Set line caps bool capChanged = false; LineCap oldStartCap = LineCap.Flat; LineCap oldEndCap = LineCap.Flat; if(this._startCap != LineAnchorCapStyle.None || this._endCap != LineAnchorCapStyle.None) { capChanged = true; oldStartCap = graphics.Pen.StartCap; oldEndCap = graphics.Pen.EndCap; // Apply anchor cap settings if(this._startCap == LineAnchorCapStyle.Arrow) { // Adjust arrow size for small line width if(this.LineWidth < 4) { int adjustment = 3 - this.LineWidth; graphics.Pen.StartCap = LineCap.Custom; graphics.Pen.CustomStartCap = new AdjustableArrowCap( this.LineWidth + adjustment, this.LineWidth + adjustment, true); } else { graphics.Pen.StartCap = LineCap.ArrowAnchor; } } else if(this._startCap == LineAnchorCapStyle.Diamond) { graphics.Pen.StartCap = LineCap.DiamondAnchor; } else if(this._startCap == LineAnchorCapStyle.Round) { graphics.Pen.StartCap = LineCap.RoundAnchor; } else if(this._startCap == LineAnchorCapStyle.Square) { graphics.Pen.StartCap = LineCap.SquareAnchor; } if(this._endCap == LineAnchorCapStyle.Arrow) { // Adjust arrow size for small line width if(this.LineWidth < 4) { int adjustment = 3 - this.LineWidth; graphics.Pen.EndCap = LineCap.Custom; graphics.Pen.CustomEndCap = new AdjustableArrowCap( this.LineWidth + adjustment, this.LineWidth + adjustment, true); } else { graphics.Pen.EndCap = LineCap.ArrowAnchor; } } else if(this._endCap == LineAnchorCapStyle.Diamond) { graphics.Pen.EndCap = LineCap.DiamondAnchor; } else if(this._endCap == LineAnchorCapStyle.Round) { graphics.Pen.EndCap = LineCap.RoundAnchor; } else if(this._endCap == LineAnchorCapStyle.Square) { graphics.Pen.EndCap = LineCap.SquareAnchor; } } if(this.Common.ProcessModePaint) { // Draw line graphics.DrawLineRel( this.LineColor, this.LineWidth, this.LineDashStyle, firstPoint, secondPoint, this.ShadowColor, this.ShadowOffset); } if(this.Common.ProcessModeRegions) { // Create line graphics path using (GraphicsPath path = new GraphicsPath()) { path.AddLine( graphics.GetAbsolutePoint(firstPoint), graphics.GetAbsolutePoint(secondPoint)); using (Pen pen = (Pen)graphics.Pen.Clone()) { // Increase pen size by 2 pixels pen.DashStyle = DashStyle.Solid; pen.Width += 2; try { path.Widen(pen); } catch (OutOfMemoryException) { // GraphicsPath.Widen incorrectly throws OutOfMemoryException // catching here and reacting by not widening } catch (ArgumentException) { } } // Add hot region this.Common.HotRegionsList.AddHotRegion( graphics, path, false, ReplaceKeywords(this.ToolTip), #if Microsoft_CONTROL String.Empty, String.Empty, String.Empty, #else // Microsoft_CONTROL ReplaceKeywords(this.Url), ReplaceKeywords(this.MapAreaAttributes), ReplaceKeywords(this.PostBackValue), #endif // Microsoft_CONTROL this, ChartElementType.Annotation); } } // Restore line caps if(capChanged) { graphics.Pen.StartCap = oldStartCap; graphics.Pen.EndCap = oldEndCap; } // Paint selection handles PaintSelectionHandles(graphics, selectionRect, null); } #endregion } /// /// VerticalLineAnnotation is a class that represents a vertical line annotation. /// [ SRDescription("DescriptionAttributeVerticalLineAnnotation_VerticalLineAnnotation"), ] #if ASPPERM_35 [AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)] #endif public class VerticalLineAnnotation : LineAnnotation { #region Construction and Initialization /// /// Default public constructor. /// public VerticalLineAnnotation() : base() { } #endregion #region Properties /// /// Gets or sets an annotation's type name. /// /// /// This property is used to get the name of each annotation type /// (e.g. Line, Rectangle, Ellipse). /// /// This property is for internal use and is hidden at design and run time. /// /// [ SRCategory("CategoryAttributeMisc"), Bindable(true), Browsable(false), EditorBrowsableAttribute(EditorBrowsableState.Never), DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden), SerializationVisibilityAttribute(SerializationVisibility.Hidden), SRDescription("DescriptionAttributeAnnotationType"), ] public override string AnnotationType { get { return "VerticalLine"; } } #endregion #region Methods /// /// Adjusts the two coordinates of the line. /// /// First line coordinate. /// Second line coordinate. /// Selection rectangle. override internal void AdjustLineCoordinates(ref PointF point1, ref PointF point2, ref RectangleF selectionRect) { // Make line vertical point2.X = point1.X; selectionRect.Width = 0f; // Call base class base.AdjustLineCoordinates(ref point1, ref point2, ref selectionRect); } #region Content Size /// /// Gets text annotation content size based on the text and font. /// /// Annotation content position. override internal RectangleF GetContentPosition() { return new RectangleF(float.NaN, float.NaN, 0f, float.NaN); } #endregion // Content Size #endregion } /// /// HorizontalLineAnnotation is a class that represents a horizontal line annotation. /// [ SRDescription("DescriptionAttributeHorizontalLineAnnotation_HorizontalLineAnnotation"), ] #if ASPPERM_35 [AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)] #endif public class HorizontalLineAnnotation : LineAnnotation { #region Construction and Initialization /// /// Default public constructor. /// public HorizontalLineAnnotation() : base() { } #endregion #region Properties /// /// Gets or sets an annotation's type name. /// /// /// This property is used to get the name of each annotation type /// (e.g. Line, Rectangle, Ellipse). /// /// This property is for internal use and is hidden at design and run time. /// /// [ SRCategory("CategoryAttributeMisc"), Bindable(true), Browsable(false), EditorBrowsableAttribute(EditorBrowsableState.Never), DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden), SerializationVisibilityAttribute(SerializationVisibility.Hidden), SRDescription("DescriptionAttributeAnnotationType"), ] public override string AnnotationType { get { return "HorizontalLine"; } } #endregion #region Methods /// /// Adjusts the two coordinates of the line. /// /// First line coordinate. /// Second line coordinate. /// Selection rectangle. override internal void AdjustLineCoordinates(ref PointF point1, ref PointF point2, ref RectangleF selectionRect) { // Make line horizontal point2.Y = point1.Y; selectionRect.Height = 0f; // Call base class base.AdjustLineCoordinates(ref point1, ref point2, ref selectionRect); } #region Content Size /// /// Gets text annotation content size based on the text and font. /// /// Annotation content position. override internal RectangleF GetContentPosition() { return new RectangleF(float.NaN, float.NaN, float.NaN, 0f); } #endregion // Content Size #endregion } }