Xamarin Public Jenkins (auto-signing) 536cd135cc Imported Upstream version 5.4.0.167
Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
2017-08-21 15:34:15 +00:00

472 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//-------------------------------------------------------------
// <copyright company=Microsoft Corporation>
// Copyright © Microsoft Corporation. All Rights Reserved.
// </copyright>
//-------------------------------------------------------------
// @owner=alexgor, deliant
//=================================================================
// File: ArrowAnnotation.cs
//
// Namespace: System.Web.UI.WebControls[Windows.Forms].Charting
//
// Classes: ArrowAnnotation
//
// Purpose: Arrow annotation classes.
//
// 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;
using System.Web.UI.DataVisualization.Charting.Borders3D;
#endif
#endregion
#if Microsoft_CONTROL
namespace System.Windows.Forms.DataVisualization.Charting
#else
namespace System.Web.UI.DataVisualization.Charting
#endif
{
#region Enumeration
/// <summary>
/// Arrow annotation styles.
/// <seealso cref="ArrowAnnotation.ArrowStyle"/>
/// </summary>
[
SRDescription("DescriptionAttributeArrowStyle_ArrowStyle")
]
public enum ArrowStyle
{
/// <summary>
/// Simple arrow.
/// </summary>
Simple,
/// <summary>
/// Arrow pointing in two directions.
/// </summary>
DoubleArrow,
/// <summary>
/// Arrow with a tail.
/// </summary>
Tailed,
}
#endregion // Enumeration
/// <summary>
/// <b>ArrowAnnotation</b> is a class class that represents an arrow annotation.
/// </summary>
/// <remarks>
/// Arrow annotations can be used to connect to points on the chart or highlight a
/// single chart area. Different arrow styles and sizes may be applied.
/// </remarks>
[
SRDescription("DescriptionAttributeArrowAnnotation_ArrowAnnotation"),
]
#if ASPPERM_35
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
#endif
public class ArrowAnnotation : Annotation
{
#region Fields
// Annotation arrow style
private ArrowStyle _arrowStyle = ArrowStyle.Simple;
// Annotation arrow size
private int _arrowSize = 5;
#endregion
#region Construction and Initialization
/// <summary>
/// Default public constructor.
/// </summary>
public ArrowAnnotation()
: base()
{
base.AnchorAlignment = ContentAlignment.TopLeft;
}
#endregion
#region Properties
#region Arrow properties
/// <summary>
/// Gets or sets the arrow style of an arrow annotation.
/// <seealso cref="ArrowSize"/>
/// </summary>
/// <value>
/// <see cref="ArrowStyle"/> of an annotation.
/// </value>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(ArrowStyle.Simple),
SRDescription("DescriptionAttributeArrowAnnotation_ArrowStyle"),
ParenthesizePropertyNameAttribute(true),
]
virtual public ArrowStyle ArrowStyle
{
get
{
return _arrowStyle;
}
set
{
_arrowStyle = value;
Invalidate();
}
}
/// <summary>
/// Gets or sets the arrow size in pixels of an arrow annotation.
/// <seealso cref="ArrowStyle"/>
/// </summary>
/// <value>
/// Integer value that represents arrow size (thickness) in pixels.
/// </value>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(5),
SRDescription("DescriptionAttributeArrowAnnotation_ArrowSize"),
ParenthesizePropertyNameAttribute(true),
]
virtual public int ArrowSize
{
get
{
return _arrowSize;
}
set
{
if(value <= 0)
{
throw(new ArgumentOutOfRangeException("value", SR.ExceptionAnnotationArrowSizeIsZero));
}
if(value > 100)
{
throw (new ArgumentOutOfRangeException("value", SR.ExceptionAnnotationArrowSizeMustBeLessThen100));
}
_arrowSize = value;
Invalidate();
}
}
#endregion // Arrow properties
#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 "Arrow";
}
}
/// <summary>
/// Gets or sets annotation selection points style.
/// </summary>
/// <value>
/// A <see cref="SelectionPointsStyle"/> value that represents 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>
/// Paints annotation object on specified graphics.
/// </summary>
/// <param name="graphics">
/// A <see cref="ChartGraphics"/> used to paint annotation object.
/// </param>
/// <param name="chart">
/// Reference to the <see cref="Chart"/> 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));
// Check if text position is valid
if( float.IsNaN(firstPoint.X) ||
float.IsNaN(firstPoint.Y) ||
float.IsNaN(secondPoint.X) ||
float.IsNaN(secondPoint.Y) )
{
return;
}
// Get arrow shape path
using (GraphicsPath arrowPathAbs = GetArrowPath(graphics, selectionRect))
{
// Draw arrow shape
if (this.Common.ProcessModePaint)
{
graphics.DrawPathAbs(
arrowPathAbs,
(this.BackColor.IsEmpty) ? Color.White : this.BackColor,
this.BackHatchStyle,
String.Empty,
ChartImageWrapMode.Scaled,
Color.Empty,
ChartImageAlignmentStyle.Center,
this.BackGradientStyle,
this.BackSecondaryColor,
this.LineColor,
this.LineWidth,
this.LineDashStyle,
PenAlignment.Center,
this.ShadowOffset,
this.ShadowColor);
}
// Process hot region
if (this.Common.ProcessModeRegions)
{
// Use callout defined hot region
this.Common.HotRegionsList.AddHotRegion(
graphics,
arrowPathAbs,
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);
}
// Paint selection handles
PaintSelectionHandles(graphics, selectionRect, null);
}
}
/// <summary>
/// Get arrow path for the specified annotation position
/// </summary>
/// <param name="graphics"></param>
/// <param name="position"></param>
/// <returns></returns>
private GraphicsPath GetArrowPath(
ChartGraphics graphics,
RectangleF position)
{
// Get absolute position
RectangleF positionAbs = graphics.GetAbsoluteRectangle(position);
PointF firstPoint = positionAbs.Location;
PointF secondPoint = new PointF(positionAbs.Right, positionAbs.Bottom);
// Calculate arrow length
float deltaX = secondPoint.X - firstPoint.X;
float deltaY = secondPoint.Y - firstPoint.Y;
float arrowLength = (float)Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
// Create unrotated graphics path for the arrow started at the annotation location
// and going to the right for the length of the rotated arrow.
GraphicsPath path = new GraphicsPath();
PointF[] points = null;
float pointerRatio = 2.1f;
if(this.ArrowStyle == ArrowStyle.Simple)
{
points = new PointF[] {
firstPoint,
new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y - this.ArrowSize*pointerRatio),
new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y - this.ArrowSize),
new PointF(firstPoint.X + arrowLength, firstPoint.Y - this.ArrowSize),
new PointF(firstPoint.X + arrowLength, firstPoint.Y + this.ArrowSize),
new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y + this.ArrowSize),
new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y + this.ArrowSize*pointerRatio) };
}
else if(this.ArrowStyle == ArrowStyle.DoubleArrow)
{
points = new PointF[] {
firstPoint,
new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y - this.ArrowSize*pointerRatio),
new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y - this.ArrowSize),
new PointF(firstPoint.X + arrowLength - this.ArrowSize*pointerRatio, firstPoint.Y - this.ArrowSize),
new PointF(firstPoint.X + arrowLength - this.ArrowSize*pointerRatio, firstPoint.Y - this.ArrowSize*pointerRatio),
new PointF(firstPoint.X + arrowLength, firstPoint.Y),
new PointF(firstPoint.X + arrowLength - this.ArrowSize*pointerRatio, firstPoint.Y + this.ArrowSize*pointerRatio),
new PointF(firstPoint.X + arrowLength - this.ArrowSize*pointerRatio, firstPoint.Y + this.ArrowSize),
new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y + this.ArrowSize),
new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y + this.ArrowSize*pointerRatio) };
}
else if(this.ArrowStyle == ArrowStyle.Tailed)
{
float tailRatio = 2.1f;
points = new PointF[] {
firstPoint,
new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y - this.ArrowSize*pointerRatio),
new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y - this.ArrowSize),
new PointF(firstPoint.X + arrowLength, firstPoint.Y - this.ArrowSize*tailRatio),
new PointF(firstPoint.X + arrowLength - this.ArrowSize*tailRatio, firstPoint.Y),
new PointF(firstPoint.X + arrowLength, firstPoint.Y + this.ArrowSize*tailRatio),
new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y + this.ArrowSize),
new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y + this.ArrowSize*pointerRatio) };
}
else
{
throw (new InvalidOperationException(SR.ExceptionAnnotationArrowStyleUnknown));
}
path.AddLines(points);
path.CloseAllFigures();
// Calculate arrow angle
float angle = (float)(Math.Atan(deltaY / deltaX) * 180f / Math.PI);
if(deltaX < 0)
{
angle += 180f;
}
// Rotate arrow path around the first point
using( Matrix matrix = new Matrix() )
{
matrix.RotateAt(angle, firstPoint);
path.Transform(matrix);
}
return path;
}
#endregion
}
}