1 //-------------------------------------------------------------
2 // <copyright company=
\92Microsoft Corporation
\92>
3 // Copyright © Microsoft Corporation. All Rights Reserved.
5 //-------------------------------------------------------------
6 // @owner=alexgor, deliant
7 //=================================================================
8 // File: ArrowAnnotation.cs
10 // Namespace: System.Web.UI.WebControls[Windows.Forms].Charting
12 // Classes: ArrowAnnotation
14 // Purpose: Arrow annotation classes.
18 //===================================================================
20 #region Used namespace
22 using System.Collections;
23 using System.Collections.Specialized;
24 using System.ComponentModel;
25 using System.ComponentModel.Design;
28 using System.Drawing.Design;
29 using System.Drawing.Text;
30 using System.Drawing.Drawing2D;
32 using System.Windows.Forms.DataVisualization.Charting;
33 using System.Windows.Forms.DataVisualization.Charting.Data;
34 using System.Windows.Forms.DataVisualization.Charting.ChartTypes;
35 using System.Windows.Forms.DataVisualization.Charting.Utilities;
36 using System.Windows.Forms.DataVisualization.Charting.Borders3D;
41 using System.Web.UI.DataVisualization.Charting;
42 using System.Web.UI.DataVisualization.Charting.Data;
43 using System.Web.UI.DataVisualization.Charting.Utilities;
44 using System.Web.UI.DataVisualization.Charting.Borders3D;
51 namespace System.Windows.Forms.DataVisualization.Charting
54 namespace System.Web.UI.DataVisualization.Charting
61 /// Arrow annotation styles.
62 /// <seealso cref="ArrowAnnotation.ArrowStyle"/>
65 SRDescription("DescriptionAttributeArrowStyle_ArrowStyle")
67 public enum ArrowStyle
75 /// Arrow pointing in two directions.
80 /// Arrow with a tail.
85 #endregion // Enumeration
88 /// <b>ArrowAnnotation</b> is a class class that represents an arrow annotation.
91 /// Arrow annotations can be used to connect to points on the chart or highlight a
92 /// single chart area. Different arrow styles and sizes may be applied.
95 SRDescription("DescriptionAttributeArrowAnnotation_ArrowAnnotation"),
98 [AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
99 [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
101 public class ArrowAnnotation : Annotation
105 // Annotation arrow style
106 private ArrowStyle _arrowStyle = ArrowStyle.Simple;
108 // Annotation arrow size
109 private int _arrowSize = 5;
113 #region Construction and Initialization
116 /// Default public constructor.
118 public ArrowAnnotation()
121 base.AnchorAlignment = ContentAlignment.TopLeft;
128 #region Arrow properties
131 /// Gets or sets the arrow style of an arrow annotation.
132 /// <seealso cref="ArrowSize"/>
135 /// <see cref="ArrowStyle"/> of an annotation.
138 SRCategory("CategoryAttributeAppearance"),
140 DefaultValue(ArrowStyle.Simple),
141 SRDescription("DescriptionAttributeArrowAnnotation_ArrowStyle"),
142 ParenthesizePropertyNameAttribute(true),
144 virtual public ArrowStyle ArrowStyle
158 /// Gets or sets the arrow size in pixels of an arrow annotation.
159 /// <seealso cref="ArrowStyle"/>
162 /// Integer value that represents arrow size (thickness) in pixels.
165 SRCategory("CategoryAttributeAppearance"),
168 SRDescription("DescriptionAttributeArrowAnnotation_ArrowSize"),
169 ParenthesizePropertyNameAttribute(true),
171 virtual public int ArrowSize
181 throw(new ArgumentOutOfRangeException("value", SR.ExceptionAnnotationArrowSizeIsZero));
185 throw (new ArgumentOutOfRangeException("value", SR.ExceptionAnnotationArrowSizeMustBeLessThen100));
193 #endregion // Arrow properties
198 /// Gets or sets an annotation position's alignment to the anchor point.
199 /// <seealso cref="Annotation.AnchorX"/>
200 /// <seealso cref="Annotation.AnchorY"/>
201 /// <seealso cref="Annotation.AnchorDataPoint"/>
202 /// <seealso cref="Annotation.AnchorOffsetX"/>
203 /// <seealso cref="Annotation.AnchorOffsetY"/>
206 /// A <see cref="ContentAlignment"/> value that represents the annotation's alignment to
207 /// the anchor point.
210 /// The annotation must be anchored using either <see cref="Annotation.AnchorDataPoint"/>, or the <see cref="Annotation.AnchorX"/>
211 /// and <see cref="Annotation.AnchorY"/> properties. Its <see cref="Annotation.X"/> and <see cref="Annotation.Y"/>
212 /// properties must be set to <b>Double.NaN</b>.
215 SRCategory("CategoryAttributeAnchor"),
217 EditorBrowsableAttribute(EditorBrowsableState.Never),
218 DefaultValue(typeof(ContentAlignment), "TopLeft"),
219 SRDescription("DescriptionAttributeAnchorAlignment"),
221 override public ContentAlignment AnchorAlignment
225 return base.AnchorAlignment;
229 base.AnchorAlignment = value;
233 #endregion // Anchoring
238 /// Gets or sets an annotation's type name.
241 /// This property is used to get the name of each annotation type
242 /// (e.g. Line, Rectangle, Ellipse).
244 /// This property is for internal use and is hidden at design and run time.
248 SRCategory("CategoryAttributeMisc"),
251 EditorBrowsableAttribute(EditorBrowsableState.Never),
252 DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
253 SerializationVisibilityAttribute(SerializationVisibility.Hidden),
254 SRDescription("DescriptionAttributeAnnotationType"),
256 public override string AnnotationType
265 /// Gets or sets annotation selection points style.
268 /// A <see cref="SelectionPointsStyle"/> value that represents annotation
272 /// This property is for internal use and is hidden at design and run time.
275 SRCategory("CategoryAttributeAppearance"),
276 DefaultValue(SelectionPointsStyle.Rectangle),
277 ParenthesizePropertyNameAttribute(true),
279 EditorBrowsableAttribute(EditorBrowsableState.Never),
280 DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
281 SerializationVisibilityAttribute(SerializationVisibility.Hidden),
282 SRDescription("DescriptionAttributeSelectionPointsStyle"),
284 override internal SelectionPointsStyle SelectionPointsStyle
288 return SelectionPointsStyle.TwoPoints;
299 /// Paints annotation object on specified graphics.
301 /// <param name="graphics">
302 /// A <see cref="ChartGraphics"/> used to paint annotation object.
304 /// <param name="chart">
305 /// Reference to the <see cref="Chart"/> control.
307 override internal void Paint(Chart chart, ChartGraphics graphics)
309 // Get annotation position in relative coordinates
310 PointF firstPoint = PointF.Empty;
311 PointF anchorPoint = PointF.Empty;
312 SizeF size = SizeF.Empty;
313 GetRelativePosition(out firstPoint, out size, out anchorPoint);
314 PointF secondPoint = new PointF(firstPoint.X + size.Width, firstPoint.Y + size.Height);
316 // Create selection rectangle
317 RectangleF selectionRect = new RectangleF(firstPoint, new SizeF(secondPoint.X - firstPoint.X, secondPoint.Y - firstPoint.Y));
319 // Check if text position is valid
320 if( float.IsNaN(firstPoint.X) ||
321 float.IsNaN(firstPoint.Y) ||
322 float.IsNaN(secondPoint.X) ||
323 float.IsNaN(secondPoint.Y) )
328 // Get arrow shape path
329 using (GraphicsPath arrowPathAbs = GetArrowPath(graphics, selectionRect))
333 if (this.Common.ProcessModePaint)
335 graphics.DrawPathAbs(
337 (this.BackColor.IsEmpty) ? Color.White : this.BackColor,
340 ChartImageWrapMode.Scaled,
342 ChartImageAlignmentStyle.Center,
343 this.BackGradientStyle,
344 this.BackSecondaryColor,
353 // Process hot region
354 if (this.Common.ProcessModeRegions)
356 // Use callout defined hot region
357 this.Common.HotRegionsList.AddHotRegion(
361 ReplaceKeywords(this.ToolTip),
362 #if Microsoft_CONTROL
366 #else // Microsoft_CONTROL
367 ReplaceKeywords(this.Url),
368 ReplaceKeywords(this.MapAreaAttributes),
369 ReplaceKeywords(this.PostBackValue),
370 #endif // Microsoft_CONTROL
372 ChartElementType.Annotation);
375 // Paint selection handles
376 PaintSelectionHandles(graphics, selectionRect, null);
381 /// Get arrow path for the specified annotation position
383 /// <param name="graphics"></param>
384 /// <param name="position"></param>
385 /// <returns></returns>
386 private GraphicsPath GetArrowPath(
387 ChartGraphics graphics,
390 // Get absolute position
391 RectangleF positionAbs = graphics.GetAbsoluteRectangle(position);
392 PointF firstPoint = positionAbs.Location;
393 PointF secondPoint = new PointF(positionAbs.Right, positionAbs.Bottom);
395 // Calculate arrow length
396 float deltaX = secondPoint.X - firstPoint.X;
397 float deltaY = secondPoint.Y - firstPoint.Y;
398 float arrowLength = (float)Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
400 // Create unrotated graphics path for the arrow started at the annotation location
401 // and going to the right for the length of the rotated arrow.
402 GraphicsPath path = new GraphicsPath();
404 PointF[] points = null;
405 float pointerRatio = 2.1f;
406 if(this.ArrowStyle == ArrowStyle.Simple)
408 points = new PointF[] {
410 new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y - this.ArrowSize*pointerRatio),
411 new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y - this.ArrowSize),
412 new PointF(firstPoint.X + arrowLength, firstPoint.Y - this.ArrowSize),
413 new PointF(firstPoint.X + arrowLength, firstPoint.Y + this.ArrowSize),
414 new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y + this.ArrowSize),
415 new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y + this.ArrowSize*pointerRatio) };
417 else if(this.ArrowStyle == ArrowStyle.DoubleArrow)
419 points = new PointF[] {
421 new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y - this.ArrowSize*pointerRatio),
422 new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y - this.ArrowSize),
423 new PointF(firstPoint.X + arrowLength - this.ArrowSize*pointerRatio, firstPoint.Y - this.ArrowSize),
424 new PointF(firstPoint.X + arrowLength - this.ArrowSize*pointerRatio, firstPoint.Y - this.ArrowSize*pointerRatio),
425 new PointF(firstPoint.X + arrowLength, firstPoint.Y),
426 new PointF(firstPoint.X + arrowLength - this.ArrowSize*pointerRatio, firstPoint.Y + this.ArrowSize*pointerRatio),
427 new PointF(firstPoint.X + arrowLength - this.ArrowSize*pointerRatio, firstPoint.Y + this.ArrowSize),
428 new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y + this.ArrowSize),
429 new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y + this.ArrowSize*pointerRatio) };
431 else if(this.ArrowStyle == ArrowStyle.Tailed)
433 float tailRatio = 2.1f;
434 points = new PointF[] {
436 new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y - this.ArrowSize*pointerRatio),
437 new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y - this.ArrowSize),
438 new PointF(firstPoint.X + arrowLength, firstPoint.Y - this.ArrowSize*tailRatio),
439 new PointF(firstPoint.X + arrowLength - this.ArrowSize*tailRatio, firstPoint.Y),
440 new PointF(firstPoint.X + arrowLength, firstPoint.Y + this.ArrowSize*tailRatio),
441 new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y + this.ArrowSize),
442 new PointF(firstPoint.X + this.ArrowSize*pointerRatio, firstPoint.Y + this.ArrowSize*pointerRatio) };
446 throw (new InvalidOperationException(SR.ExceptionAnnotationArrowStyleUnknown));
449 path.AddLines(points);
450 path.CloseAllFigures();
452 // Calculate arrow angle
453 float angle = (float)(Math.Atan(deltaY / deltaX) * 180f / Math.PI);
459 // Rotate arrow path around the first point
460 using( Matrix matrix = new Matrix() )
462 matrix.RotateAt(angle, firstPoint);
463 path.Transform(matrix);