File: Common\Annotation\LineAnnotation.cs
Project: ndp\fx\src\DataVisualization\System.Windows.Forms.DataVisualization.csproj (System.Windows.Forms.DataVisualization)
//-------------------------------------------------------------
// <copyright company=’Microsoft Corporation’>
//   Copyright © Microsoft Corporation. All Rights Reserved.
// </copyright>
//-------------------------------------------------------------
// @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
{
	/// <summary>
	/// <b>LineAnnotation</b> is a class that represents a line annotation.
	/// </summary>
	[
		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
 
		/// <summary>
		/// Default public constructor.
		/// </summary>
		public LineAnnotation() 
            : base()
		{
			this.anchorAlignment = ContentAlignment.TopLeft;
		}
 
		#endregion
 
		#region Properties
 
		#region Line Visual Attributes
 
		/// <summary>
		/// Gets or sets a flag that indicates if an infinitive line should be drawn.
		/// </summary>
		/// <value>
		/// <b>True</b> if a line should be drawn infinitively through 2 points provided, <b>false</b> otherwise.
		/// </value>
		[
		SRCategory("CategoryAttributeAppearance"),
		DefaultValue(false),
		SRDescription("DescriptionAttributeDrawInfinitive"),
		]
		virtual public bool IsInfinitive
		{
			get
			{
				return _isInfinitive;
			}
			set
			{
				_isInfinitive = value;
				Invalidate();
			}
		}
 
		/// <summary>
		/// Gets or sets a cap style used at the start of an annotation line.
		/// <seealso cref="EndCap"/>
		/// </summary>
		/// <value>
        /// A <see cref="LineAnchorCapStyle"/> value, used for a cap style used at the start of an annotation line.
		/// </value>
		[
		SRCategory("CategoryAttributeAppearance"),
		DefaultValue(LineAnchorCapStyle.None),
		SRDescription("DescriptionAttributeStartCap3"),
		]
		virtual public LineAnchorCapStyle StartCap
		{
			get
			{
				return _startCap;
			}
			set
			{
				_startCap = value;
				Invalidate();
			}
		}
 
		/// <summary>
		/// Gets or sets a cap style used at the end of an annotation line.
		/// <seealso cref="StartCap"/>
		/// </summary>
		/// <value>
        /// A <see cref="LineAnchorCapStyle"/> value, used for a cap style used at the end of an annotation line.
		/// </value>
		[
		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)
 
		/// <summary>
		/// Not applicable to this annotation type.
		/// </summary>
		/// <value>
		/// A <see cref="ContentAlignment"/> value.
		/// </value>
		[
		SRCategory("CategoryAttributeAppearance"),
		Browsable(false),
		DefaultValue(typeof(ContentAlignment), "MiddleCenter"),
		]
		override public ContentAlignment Alignment
		{
			get
			{
				return base.Alignment;
			}
			set
			{
				base.Alignment = value;
			}
		}
 
        /// <summary>
        /// Gets or sets an annotation's text style.
        /// <seealso cref="Font"/>
        /// 	<seealso cref="ForeColor"/>
        /// </summary>
        /// <value>
        /// A <see cref="TextStyle"/> value used to draw an annotation's text.
        /// </value>
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public override TextStyle TextStyle
        {
            get
            {
                return base.TextStyle;
            }
            set
            {
                base.TextStyle = value;
            }
        }
 
		/// <summary>
		/// Not applicable to this annotation type.
		/// <seealso cref="Font"/>
		/// </summary>
		/// <value>
		/// A <see cref="Color"/> value.
		/// </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;
			}
		}
 
		/// <summary>
		/// Not applicable to this annotation type.
		/// <seealso cref="ForeColor"/>
		/// </summary>
		/// <value>
		/// A <see cref="Font"/> object.
		/// </value>
		[
		SRCategory("CategoryAttributeAppearance"),
		Browsable(false),
		DefaultValue(typeof(Font), "Microsoft Sans Serif, 8pt"),
		]
		override public Font Font
		{
			get
			{
				return base.Font;
			}
			set
			{
				base.Font = value;
			}
		}
 
        /// <summary>
        /// Not applicable to this annotation type.
        /// </summary>
		[
		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;
			}
		}
 
		/// <summary>
		/// Not applicable to this annotation type.
		/// </summary>
		/// <value>
		/// A <see cref="ChartHatchStyle"/> value.
		/// </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;
			}
		}
 
        /// <summary>
        /// Not applicable to this annotation type.
        /// </summary>
		[
		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;
			}
		}
 
        /// <summary>
        /// Not applicable to this annotation type.
        /// </summary>
		[
		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
 
        /// <summary>
        /// Gets or sets a flag that specifies whether the size of an annotation is always 
        /// defined in relative chart coordinates.
        /// <seealso cref="Annotation.Width"/>
        /// <seealso cref="Annotation.Height"/>
        /// </summary>
        /// <value>
        /// <b>True</b> if an annotation's <see cref="Annotation.Width"/> and <see cref="Annotation.Height"/> are always 
        /// in chart relative coordinates, <b>false</b> otherwise.
        /// </value>
        /// <remarks>
        /// An annotation's width and height may be set in relative chart or axes coordinates. 
        /// By default, relative chart coordinates are used.
        /// <para>
        /// To use axes coordinates for size set the <b>IsSizeAlwaysRelative</b> property to 
        /// <b>false</b> and either anchor the annotation to a data point or set the 
        /// <see cref="Annotation.AxisX"/> or <see cref="Annotation.AxisY"/> properties.
        /// </para>
        /// </remarks>
		[
		SRCategory("CategoryAttributePosition"),
		DefaultValue(true),
		SRDescription("DescriptionAttributeSizeAlwaysRelative3"),
		]
		override public bool IsSizeAlwaysRelative
		{
			get
			{
				return base.IsSizeAlwaysRelative;
			}
			set
			{
				base.IsSizeAlwaysRelative = value;
			}
		}
 
		#endregion // Position
 
		#region Anchor
 
        /// <summary>
        /// Gets or sets an annotation position's alignment to the anchor point.
        /// <seealso cref="Annotation.AnchorX"/>
        /// <seealso cref="Annotation.AnchorY"/>
        /// <seealso cref="Annotation.AnchorDataPoint"/>
        /// <seealso cref="Annotation.AnchorOffsetX"/>
        /// <seealso cref="Annotation.AnchorOffsetY"/>
        /// </summary>
        /// <value>
        /// A <see cref="ContentAlignment"/> value that represents the annotation's alignment to 
        /// the anchor point.
        /// </value>
        /// <remarks>
        /// The annotation must be anchored using either <see cref="Annotation.AnchorDataPoint"/>, or the <see cref="Annotation.AnchorX"/> 
        /// and <see cref="Annotation.AnchorY"/> properties. Its <see cref="Annotation.X"/> and <see cref="Annotation.Y"/> 
        /// properties must be set to <b>Double.NaN</b>.
        /// </remarks>
		[
		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
 
        /// <summary>
        /// Gets or sets an annotation's type name.
        /// </summary>
        /// <remarks>
        /// This property is used to get the name of each annotation type 
        /// (e.g. Line, Rectangle, Ellipse). 
        /// <para>
        /// This property is for internal use and is hidden at design and run time.
        /// </para>
        /// </remarks>
		[
		SRCategory("CategoryAttributeMisc"),
		Bindable(true),
		Browsable(false),
		EditorBrowsableAttribute(EditorBrowsableState.Never),
		DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
		SerializationVisibilityAttribute(SerializationVisibility.Hidden),
		SRDescription("DescriptionAttributeAnnotationType"),
		]
		public override string AnnotationType
		{
			get
			{
				return "Line";
			}
		}
 
		/// <summary>
		/// Gets or sets an annotation's selection points style.
		/// </summary>
		/// <value>
		/// A <see cref="SelectionPointsStyle"/> value that represents the annotation
		/// selection style.
		/// </value>
		/// <remarks>
        /// This property is for internal use and is hidden at design and run time.
		/// </remarks>
		[
		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
 
		/// <summary>
		/// Adjusts the two coordinates of the line.
		/// </summary>
		/// <param name="point1">First line coordinate.</param>
		/// <param name="point2">Second line coordinate.</param>
		/// <param name="selectionRect">Selection rectangle.</param>
		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;
				}
			}
		}
 
		/// <summary>
		/// Paints an annotation object on the specified graphics.
		/// </summary>
		/// <param name="graphics">
		/// A <see cref="ChartGraphics"/> object, used to paint an annotation object.
		/// </param>
		/// <param name="chart">
		/// Reference to the <see cref="Chart"/> owner control.
		/// </param>
        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
	}
 
	/// <summary>
	/// <b>VerticalLineAnnotation</b> is a class that represents a vertical line annotation.
	/// </summary>
	[
		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
 
		/// <summary>
		/// Default public constructor.
		/// </summary>
		public VerticalLineAnnotation() 
            : base()
		{
		}
 
		#endregion
 
		#region Properties
 
        /// <summary>
        /// Gets or sets an annotation's type name.
        /// </summary>
        /// <remarks>
        /// This property is used to get the name of each annotation type 
        /// (e.g. Line, Rectangle, Ellipse). 
        /// <para>
        /// This property is for internal use and is hidden at design and run time.
        /// </para>
        /// </remarks>
		[
		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
 
		/// <summary>
		/// Adjusts the two coordinates of the line.
		/// </summary>
		/// <param name="point1">First line coordinate.</param>
		/// <param name="point2">Second line coordinate.</param>
		/// <param name="selectionRect">Selection rectangle.</param>
		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
 
		/// <summary>
		/// Gets text annotation content size based on the text and font.
		/// </summary>
		/// <returns>Annotation content position.</returns>
		override internal RectangleF GetContentPosition()
		{
			return new RectangleF(float.NaN, float.NaN, 0f, float.NaN);
		}
 
		#endregion // Content Size
 
		#endregion
	}
 
	/// <summary>
	/// <b>HorizontalLineAnnotation</b> is a class that represents a horizontal line annotation.
	/// </summary>
	[
		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
 
		/// <summary>
		/// Default public constructor.
		/// </summary>
		public HorizontalLineAnnotation() 
            : base()
		{
		}
 
		#endregion
 
		#region Properties
 
        /// <summary>
        /// Gets or sets an annotation's type name.
        /// </summary>
        /// <remarks>
        /// This property is used to get the name of each annotation type 
        /// (e.g. Line, Rectangle, Ellipse). 
        /// <para>
        /// This property is for internal use and is hidden at design and run time.
        /// </para>
        /// </remarks>
		[
		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
 
		/// <summary>
		/// Adjusts the two coordinates of the line.
		/// </summary>
		/// <param name="point1">First line coordinate.</param>
		/// <param name="point2">Second line coordinate.</param>
		/// <param name="selectionRect">Selection rectangle.</param>
		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
 
		/// <summary>
		/// Gets text annotation content size based on the text and font.
		/// </summary>
		/// <returns>Annotation content position.</returns>
		override internal RectangleF GetContentPosition()
		{
			return new RectangleF(float.NaN, float.NaN, float.NaN, 0f);
		}
 
		#endregion // Content Size
 
		#endregion
	}
}