You've already forked linux-packaging-mono
Rewrite with hard-coded offsets into the PE file format to discern if a binary is PE32 or PE32+, and then to determine if it contains a "CLR Data Directory" entry that looks valid. Tested with PE32 and PE32+ compiled Mono binaries, PE32 and PE32+ native binaries, and a random assortment of garbage files. Former-commit-id: 9e7ac86ec84f653a2f79b87183efd5b0ebda001b
4438 lines
131 KiB
C#
4438 lines
131 KiB
C#
//-------------------------------------------------------------
|
||
// <copyright company=’Microsoft Corporation’>
|
||
// Copyright © Microsoft Corporation. All Rights Reserved.
|
||
// </copyright>
|
||
//-------------------------------------------------------------
|
||
// @owner=alexgor, deliant
|
||
//=================================================================
|
||
// File: Annotation.cs
|
||
//
|
||
// Namespace: System.Web.UI.WebControls[Windows.Forms].Charting
|
||
//
|
||
// Classes: Annotation, AnnotationPositionChangingEventArgs
|
||
//
|
||
// Purpose: Base class for all anotation objects. Provides
|
||
// basic set of properties and methods.
|
||
//
|
||
// Reviewed:
|
||
//
|
||
//===================================================================
|
||
|
||
#region Used namespace
|
||
using System;
|
||
using System.Collections;
|
||
using System.Collections.Specialized;
|
||
using System.ComponentModel;
|
||
using System.ComponentModel.Design;
|
||
using System.Globalization;
|
||
using System.Data;
|
||
using System.Drawing;
|
||
using System.Drawing.Design;
|
||
using System.Drawing.Text;
|
||
using System.Drawing.Drawing2D;
|
||
using System.Diagnostics;
|
||
using System.Diagnostics.CodeAnalysis;
|
||
|
||
#if Microsoft_CONTROL
|
||
using System.ComponentModel.Design.Serialization;
|
||
using System.Reflection;
|
||
using System.Windows.Forms;
|
||
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
|
||
{
|
||
#region Enumerations
|
||
|
||
/// <summary>
|
||
/// Annotation object selection points style.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Enumeration is for internal use only and should not be part of the documentation.
|
||
/// </remarks>
|
||
internal enum SelectionPointsStyle
|
||
{
|
||
/// <summary>
|
||
/// Selection points are displayed top left and bottom right corners
|
||
/// </summary>
|
||
TwoPoints,
|
||
|
||
/// <summary>
|
||
/// Selection points are displayed on all sides and corners of the rectangle.
|
||
/// </summary>
|
||
Rectangle,
|
||
}
|
||
|
||
/// <summary>
|
||
/// Annotation object resizing\moving mode.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Enumeration is for internal use only and should not be part of the documentation.
|
||
/// </remarks>
|
||
internal enum ResizingMode
|
||
{
|
||
/// <summary>
|
||
/// Top Left selection handle is used.
|
||
/// </summary>
|
||
TopLeftHandle = 0,
|
||
/// <summary>
|
||
/// Top selection handle is used.
|
||
/// </summary>
|
||
TopHandle = 1,
|
||
/// <summary>
|
||
/// Top Right selection handle is used.
|
||
/// </summary>
|
||
TopRightHandle = 2,
|
||
/// <summary>
|
||
/// Right selection handle is used.
|
||
/// </summary>
|
||
RightHandle = 3,
|
||
/// <summary>
|
||
/// Bottom Right selection handle is used.
|
||
/// </summary>
|
||
BottomRightHandle = 4,
|
||
/// <summary>
|
||
/// Bottom selection handle is used.
|
||
/// </summary>
|
||
BottomHandle = 5,
|
||
/// <summary>
|
||
/// Bottom Left selection handle is used.
|
||
/// </summary>
|
||
BottomLeftHandle = 6,
|
||
/// <summary>
|
||
/// Left selection handle is used.
|
||
/// </summary>
|
||
LeftHandle = 7,
|
||
/// <summary>
|
||
/// Anchor selection handle is used.
|
||
/// </summary>
|
||
AnchorHandle = 8,
|
||
/// <summary>
|
||
/// No selection handles used - moving mode.
|
||
/// </summary>
|
||
Moving = 16,
|
||
/// <summary>
|
||
/// Moving points of the annotation path.
|
||
/// </summary>
|
||
MovingPathPoints = 32,
|
||
/// <summary>
|
||
/// No moving or resizing.
|
||
/// </summary>
|
||
None = 64,
|
||
}
|
||
|
||
#endregion
|
||
|
||
/// <summary>
|
||
/// <b>Annotation</b> is an abstract class that defines properties and methods
|
||
/// common to all annotations.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// All annotations are derived from the <b>Annotation</b> class, which can be
|
||
/// used to set properties common to all annotation objects (e.g. color, position,
|
||
/// anchoring and others).
|
||
/// </remarks>
|
||
[
|
||
SRDescription("DescriptionAttributeAnnotation_Annotation"),
|
||
DefaultProperty("Name"),
|
||
]
|
||
#if ASPPERM_35
|
||
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
|
||
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
|
||
#endif
|
||
#if !Microsoft_CONTROL
|
||
public abstract class Annotation : ChartNamedElement, IChartMapArea
|
||
#else
|
||
public abstract class Annotation : ChartNamedElement
|
||
#endif
|
||
{
|
||
#region Fields
|
||
|
||
|
||
// Name of the chart area the annotation is clipped to
|
||
private string _clipToChartArea = Constants.NotSetValue;
|
||
|
||
// Indicates that annotation is selected
|
||
private bool _isSelected = false;
|
||
|
||
// Indicates that annotation size is defined in relative chart coordinates
|
||
private bool _isSizeAlwaysRelative = true;
|
||
|
||
// Position attribute fields
|
||
private double _x = double.NaN;
|
||
private double _y = double.NaN;
|
||
private double _width = double.NaN;
|
||
private double _height = double.NaN;
|
||
|
||
// Annotation axes attaching fields
|
||
private string _axisXName = String.Empty;
|
||
private string _axisYName = String.Empty;
|
||
private Axis _axisX = null;
|
||
private Axis _axisY = null;
|
||
|
||
// Visual attribute fields
|
||
private bool _visible = true;
|
||
private ContentAlignment _alignment = ContentAlignment.MiddleCenter;
|
||
private Color _foreColor = Color.Black;
|
||
private FontCache _fontCache = new FontCache();
|
||
private Font _textFont;
|
||
private TextStyle _textStyle = TextStyle.Default;
|
||
internal Color lineColor = Color.Black;
|
||
private int _lineWidth = 1;
|
||
private ChartDashStyle _lineDashStyle = ChartDashStyle.Solid;
|
||
private Color _backColor = Color.Empty;
|
||
private ChartHatchStyle _backHatchStyle = ChartHatchStyle.None;
|
||
private GradientStyle _backGradientStyle = GradientStyle.None;
|
||
private Color _backSecondaryColor = Color.Empty;
|
||
private Color _shadowColor = Color.FromArgb(128, 0, 0, 0);
|
||
private int _shadowOffset = 0;
|
||
|
||
// Anchor position attribute fields
|
||
private string _anchorDataPointName = String.Empty;
|
||
private DataPoint _anchorDataPoint = null;
|
||
private DataPoint _anchorDataPoint2 = null;
|
||
private double _anchorX = double.NaN;
|
||
private double _anchorY = double.NaN;
|
||
internal double anchorOffsetX = 0.0;
|
||
internal double anchorOffsetY = 0.0;
|
||
internal ContentAlignment anchorAlignment = ContentAlignment.BottomCenter;
|
||
|
||
// Selection handles position (starting top-left and moving clockwise)
|
||
internal RectangleF[] selectionRects = null;
|
||
|
||
// Annotation tooltip
|
||
private string _tooltip = String.Empty;
|
||
|
||
// Selection handles size
|
||
internal const int selectionMarkerSize = 6;
|
||
|
||
// Pre calculated relative position of annotation and anchor point
|
||
internal RectangleF currentPositionRel = new RectangleF(float.NaN, float.NaN, float.NaN, float.NaN);
|
||
internal PointF currentAnchorLocationRel = new PointF(float.NaN, float.NaN);
|
||
|
||
// Smart labels style
|
||
private AnnotationSmartLabelStyle _smartLabelStyle = null;
|
||
|
||
// Index of last selected point in the annotation path
|
||
internal int currentPathPointIndex = -1;
|
||
|
||
// Group this annotation belongs too
|
||
internal AnnotationGroup annotationGroup = null;
|
||
|
||
#if Microsoft_CONTROL
|
||
|
||
// Selection and editing permissions
|
||
private bool _allowSelecting = false;
|
||
private bool _allowMoving = false;
|
||
private bool _allowAnchorMoving = false;
|
||
private bool _allowResizing = false;
|
||
private bool _allowTextEditing = false;
|
||
private bool _allowPathEditing = false;
|
||
|
||
#endif //Microsoft_CONTROL
|
||
|
||
#if Microsoft_CONTROL
|
||
|
||
// Indicates that annotation position was changed. Flag used to fire events.
|
||
internal bool positionChanged = false;
|
||
|
||
// Relative location of last placement position
|
||
internal PointF lastPlacementPosition = PointF.Empty;
|
||
|
||
// Relative location of annotation anchor, when it's started to move
|
||
internal PointF startMoveAnchorLocationRel = PointF.Empty;
|
||
|
||
#endif // Microsoft_CONTROL
|
||
|
||
// Relative position of annotation, when it's started to move/resize
|
||
internal RectangleF startMovePositionRel = RectangleF.Empty;
|
||
|
||
// Relative position of annotation, when it's started to move/resize
|
||
internal GraphicsPath startMovePathRel = null;
|
||
|
||
#if !Microsoft_CONTROL
|
||
|
||
// Annotation map area attributes
|
||
private string _url = String.Empty;
|
||
private string _mapAreaAttributes = String.Empty;
|
||
private string _postbackValue = String.Empty;
|
||
|
||
#endif // !Microsoft_CONTROL
|
||
|
||
/// <summary>
|
||
/// Limit of annotation width and height.
|
||
/// </summary>
|
||
internal static double WidthHightLimit = 290000000;
|
||
|
||
#endregion
|
||
|
||
#region Constructors
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="Annotation"/> class.
|
||
/// </summary>
|
||
protected Annotation()
|
||
{
|
||
_textFont = _fontCache.DefaultFont;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Properties
|
||
|
||
#region Miscellaneous
|
||
|
||
/// <summary>
|
||
/// Gets or sets an annotation's unique name.
|
||
/// </summary>
|
||
/// <value>
|
||
/// A <b>string</b> that represents an annotation's unique name.
|
||
/// </value>
|
||
[
|
||
SRCategory("CategoryAttributeMisc"),
|
||
Bindable(true),
|
||
SRDescription("DescriptionAttributeName4"),
|
||
ParenthesizePropertyNameAttribute(true),
|
||
]
|
||
public override string Name
|
||
{
|
||
get
|
||
{
|
||
return base.Name;
|
||
}
|
||
set
|
||
{
|
||
base.Name = value;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets an annotation's type name.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This property is used to get the name of each annotation Style
|
||
/// (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("DescriptionAttributeAnnotation_AnnotationType"),
|
||
]
|
||
public abstract string AnnotationType
|
||
{
|
||
get;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Gets or sets the name of the chart area which an annotation is clipped to.
|
||
/// </summary>
|
||
/// <value>
|
||
/// A string which represents the name of an existing chart area.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// If the chart area name is specified, an annotation will only be drawn inside the
|
||
/// plotting area of the chart area specified. All parts of the annotation
|
||
/// outside of the plotting area will be clipped.
|
||
/// <para>
|
||
/// To disable chart area clipping, set the property to "NotSet" or an empty string.
|
||
/// </para>
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributeMisc"),
|
||
DefaultValue(Constants.NotSetValue),
|
||
SRDescription("DescriptionAttributeAnnotationClipToChartArea"),
|
||
TypeConverter(typeof(LegendAreaNameConverter))
|
||
]
|
||
virtual public string ClipToChartArea
|
||
{
|
||
get
|
||
{
|
||
return _clipToChartArea;
|
||
}
|
||
set
|
||
{
|
||
if (value != _clipToChartArea)
|
||
{
|
||
if (String.IsNullOrEmpty(value))
|
||
{
|
||
_clipToChartArea = Constants.NotSetValue;
|
||
}
|
||
else
|
||
{
|
||
if (Chart != null && Chart.ChartAreas != null)
|
||
{
|
||
Chart.ChartAreas.VerifyNameReference(value);
|
||
}
|
||
_clipToChartArea = value;
|
||
}
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Gets or sets the smart labels style of an annotation.
|
||
/// </summary>
|
||
/// <value>
|
||
/// An <see cref="AnnotationSmartLabelStyle"/> object that represents an annotation's
|
||
/// smart labels style properties.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// Smart labels are used to prevent an annotation from overlapping data point labels
|
||
/// and other annotations.
|
||
/// <para>
|
||
/// Note that data point labels must also have smart labels enabled.
|
||
/// </para>
|
||
/// </remarks>
|
||
[
|
||
Browsable(true),
|
||
SRCategory("CategoryAttributeMisc"),
|
||
Bindable(true),
|
||
SRDescription("DescriptionAttributeSmartLabels"),
|
||
#if Microsoft_CONTROL
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
|
||
#else
|
||
PersistenceMode(PersistenceMode.InnerProperty),
|
||
#endif
|
||
]
|
||
public AnnotationSmartLabelStyle SmartLabelStyle
|
||
{
|
||
get
|
||
{
|
||
if (this._smartLabelStyle == null)
|
||
{
|
||
this._smartLabelStyle = new AnnotationSmartLabelStyle(this);
|
||
}
|
||
return _smartLabelStyle;
|
||
}
|
||
set
|
||
{
|
||
value.chartElement = this;
|
||
_smartLabelStyle = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets the group, if any, the annotation belongs to.
|
||
/// </summary>
|
||
[
|
||
Browsable(false),
|
||
DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
|
||
SerializationVisibilityAttribute(SerializationVisibility.Hidden),
|
||
]
|
||
public AnnotationGroup AnnotationGroup
|
||
{
|
||
get { return this.annotationGroup; }
|
||
}
|
||
|
||
#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="Width"/>
|
||
/// <seealso cref="Height"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// <b>True</b> if an annotation's <see cref="Width"/> and <see cref="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="AxisX"/> or <see cref="AxisY"/> properties.
|
||
/// </para>
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributePosition"),
|
||
DefaultValue(true),
|
||
SRDescription("DescriptionAttributeSizeAlwaysRelative"),
|
||
]
|
||
virtual public bool IsSizeAlwaysRelative
|
||
{
|
||
get
|
||
{
|
||
return _isSizeAlwaysRelative;
|
||
}
|
||
set
|
||
{
|
||
_isSizeAlwaysRelative = value;
|
||
this.ResetCurrentRelativePosition();
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the X coordinate of an annotation.
|
||
/// <seealso cref="AnchorDataPoint"/>
|
||
/// <seealso cref="AnchorX"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// A Double value that represents the X coordinate of an annotation.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// The X coordinate of an annotation is in relative chart coordinates or axes coordinates. Chart
|
||
/// relative coordinates are used by default.
|
||
/// <para>
|
||
/// To use axes coordinates, anchor
|
||
/// an annotation to a data point using the <see cref="AnchorDataPoint"/> property, or
|
||
/// set the annotation axes using the <see cref="AxisX"/> or <see cref="AxisY"/> properties.
|
||
/// </para>
|
||
/// <para>
|
||
/// Set the X position to Double.NaN ("NotSet") to achieve automatic position calculation
|
||
/// when the annotation is anchored using the <see cref="AnchorDataPoint"/> property or
|
||
/// the <see cref="AnchorX"/> and <see cref="AnchorY"/> properties.
|
||
/// </para>
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributePosition"),
|
||
DefaultValue(double.NaN),
|
||
SRDescription("DescriptionAttributeAnnotationBaseX"),
|
||
RefreshPropertiesAttribute(RefreshProperties.All),
|
||
TypeConverter(typeof(DoubleNanValueConverter)),
|
||
]
|
||
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "X")]
|
||
virtual public double X
|
||
{
|
||
get
|
||
{
|
||
return _x;
|
||
}
|
||
set
|
||
{
|
||
_x = value;
|
||
this.ResetCurrentRelativePosition();
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the Y coordinate of an annotation.
|
||
/// <seealso cref="AnchorDataPoint"/>
|
||
/// <seealso cref="AnchorY"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// A Double value that represents the Y coordinate of an annotation.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// The Y coordinate of an annotation is in relative chart coordinates or axes coordinates. Chart
|
||
/// relative coordinates are used by default.
|
||
/// <para>
|
||
/// To use axes coordinates, anchor
|
||
/// an annotation to a data point using the <see cref="AnchorDataPoint"/> property, or
|
||
/// set the annotation axes using the <see cref="AxisX"/> or <see cref="AxisY"/> properties.
|
||
/// </para>
|
||
/// <para>
|
||
/// Set the Y position to Double.NaN ("NotSet") to achieve automatic position calculation
|
||
/// when the annotation is anchored using the <see cref="AnchorDataPoint"/> property or
|
||
/// the <see cref="AnchorX"/> and <see cref="AnchorY"/> properties.
|
||
/// </para>
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributePosition"),
|
||
DefaultValue(double.NaN),
|
||
SRDescription("DescriptionAttributeAnnotationBaseY"),
|
||
RefreshPropertiesAttribute(RefreshProperties.All),
|
||
TypeConverter(typeof(DoubleNanValueConverter)),
|
||
]
|
||
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Y")]
|
||
virtual public double Y
|
||
{
|
||
get
|
||
{
|
||
return _y;
|
||
}
|
||
set
|
||
{
|
||
_y = value;
|
||
this.ResetCurrentRelativePosition();
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets an annotation's width.
|
||
/// <seealso cref="IsSizeAlwaysRelative"/>
|
||
/// <seealso cref="AxisX"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// A Double value that represents an annotation's width.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// An annotation's width can be a negative value, in which case the annotation orientation
|
||
/// is switched.
|
||
/// <para>
|
||
/// Annotation width can be in relative chart or axes coordinates. Chart
|
||
/// relative coordinates are used by default.
|
||
/// </para>
|
||
/// <para>
|
||
/// To use axes coordinates, anchor
|
||
/// an annotation to a data point using the <see cref="AnchorDataPoint"/> property, or
|
||
/// set the annotation axes using the <see cref="AxisX"/> or <see cref="AxisY"/> properties
|
||
/// and set the <see cref="IsSizeAlwaysRelative"/> property to <b>false</b>.
|
||
/// </para>
|
||
/// <para>
|
||
/// Set the width to Double.NaN ("NotSet") to achieve automatic size calculation for
|
||
/// annotations with text. The size will automatically be calculated based on
|
||
/// the annotation text and font size.
|
||
/// </para>
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributePosition"),
|
||
DefaultValue(double.NaN),
|
||
SRDescription("DescriptionAttributeAnnotationWidth"),
|
||
RefreshPropertiesAttribute(RefreshProperties.All),
|
||
TypeConverter(typeof(DoubleNanValueConverter)),
|
||
]
|
||
virtual public double Width
|
||
{
|
||
get
|
||
{
|
||
return _width;
|
||
}
|
||
set
|
||
{
|
||
if (value < -WidthHightLimit || value > WidthHightLimit)
|
||
{
|
||
throw new ArgumentException(SR.ExceptionValueMustBeInRange("Width", (-WidthHightLimit).ToString(CultureInfo.CurrentCulture), WidthHightLimit.ToString(CultureInfo.CurrentCulture)));
|
||
}
|
||
_width = value;
|
||
this.ResetCurrentRelativePosition();
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets an annotation's height.
|
||
/// <seealso cref="IsSizeAlwaysRelative"/>
|
||
/// <seealso cref="AxisY"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// A Double value that represents an annotation's height.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// An annotation's height can be a negative value, in which case the annotation orientation
|
||
/// is switched.
|
||
/// <para>
|
||
/// Annotation height can be in relative chart or axes coordinates. Chart
|
||
/// relative coordinates are used by default.
|
||
/// </para>
|
||
/// <para>
|
||
/// To use axes coordinates, anchor
|
||
/// an annotation to a data point using the <see cref="AnchorDataPoint"/> property, or
|
||
/// set the annotation axes using the <see cref="AxisX"/> or <see cref="AxisY"/> properties
|
||
/// and set the <see cref="IsSizeAlwaysRelative"/> property to <b>false</b>.
|
||
/// </para>
|
||
/// <para>
|
||
/// Set the height to Double.NaN ("NotSet") to achieve automatic size calculation for
|
||
/// annotations with text. The size will automatically be calculated based on
|
||
/// the annotation text and font size.
|
||
/// </para>
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributePosition"),
|
||
DefaultValue(double.NaN),
|
||
SRDescription("DescriptionAttributeAnnotationHeight"),
|
||
RefreshPropertiesAttribute(RefreshProperties.All),
|
||
TypeConverter(typeof(DoubleNanValueConverter)),
|
||
]
|
||
virtual public double Height
|
||
{
|
||
get
|
||
{
|
||
return _height;
|
||
}
|
||
set
|
||
{
|
||
if (value < -WidthHightLimit || value > WidthHightLimit)
|
||
{
|
||
throw new ArgumentException(SR.ExceptionValueMustBeInRange("Height", (-WidthHightLimit).ToString(CultureInfo.CurrentCulture), WidthHightLimit.ToString(CultureInfo.CurrentCulture)));
|
||
}
|
||
_height = value;
|
||
this.ResetCurrentRelativePosition();
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets an annotation position's right boundary.
|
||
/// <seealso cref="IsSizeAlwaysRelative"/>
|
||
/// <seealso cref="AxisX"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// A Double value that represents the position of an annotation's right boundary.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// To use axes coordinates, anchor
|
||
/// an annotation to a data point using the <see cref="AnchorDataPoint"/> property, or
|
||
/// set the annotation axes using the <see cref="AxisX"/> or <see cref="AxisY"/> properties
|
||
/// and set the <see cref="IsSizeAlwaysRelative"/> property to <b>false</b>.
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributePosition"),
|
||
DefaultValue(double.NaN),
|
||
SRDescription("DescriptionAttributeRight3"),
|
||
RefreshPropertiesAttribute(RefreshProperties.All),
|
||
Browsable(false),
|
||
DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
|
||
SerializationVisibilityAttribute(SerializationVisibility.Hidden),
|
||
TypeConverter(typeof(DoubleNanValueConverter)),
|
||
]
|
||
virtual public double Right
|
||
{
|
||
get
|
||
{
|
||
return _x + _width;
|
||
}
|
||
set
|
||
{
|
||
_width = value - _x;
|
||
this.ResetCurrentRelativePosition();
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets an annotation position's bottom boundary.
|
||
/// <seealso cref="IsSizeAlwaysRelative"/>
|
||
/// <seealso cref="AxisX"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// A Double value that represents the position of an annotation's bottom boundary.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// To use axes coordinates, anchor
|
||
/// an annotation to a data point using the <see cref="AnchorDataPoint"/> property, or
|
||
/// set the annotation axes using the <see cref="AxisX"/> or <see cref="AxisY"/> properties
|
||
/// and set the <see cref="IsSizeAlwaysRelative"/> property to <b>false</b>.
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributePosition"),
|
||
DefaultValue(double.NaN),
|
||
SRDescription("DescriptionAttributeBottom"),
|
||
RefreshPropertiesAttribute(RefreshProperties.All),
|
||
Browsable(false),
|
||
DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
|
||
SerializationVisibilityAttribute(SerializationVisibility.Hidden),
|
||
TypeConverter(typeof(DoubleNanValueConverter)),
|
||
]
|
||
virtual public double Bottom
|
||
{
|
||
get
|
||
{
|
||
return _y + _height;
|
||
}
|
||
set
|
||
{
|
||
_height = value - _y;
|
||
this.ResetCurrentRelativePosition();
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Visual Attributes
|
||
|
||
#if Microsoft_CONTROL
|
||
/// <summary>
|
||
/// Gets or sets a flag that determines if an annotation is selected.
|
||
/// <seealso cref="AllowSelecting"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// <b>True</b> if the annotation is selected, <b>false</b> otherwise.
|
||
/// </value>
|
||
#else
|
||
/// <summary>
|
||
/// Gets or sets a flag that determines if an annotation is selected.
|
||
/// </summary>
|
||
/// <value>
|
||
/// <b>True</b> if the annotation is selected, <b>false</b> otherwise.
|
||
/// </value>
|
||
#endif // Microsoft_CONTROL
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
DefaultValue(false),
|
||
Browsable(false),
|
||
SRDescription("DescriptionAttributeSelected"),
|
||
]
|
||
virtual public bool IsSelected
|
||
{
|
||
get
|
||
{
|
||
return _isSelected;
|
||
}
|
||
set
|
||
{
|
||
_isSelected = value;
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets an 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"),
|
||
]
|
||
virtual internal SelectionPointsStyle SelectionPointsStyle
|
||
{
|
||
get
|
||
{
|
||
return SelectionPointsStyle.Rectangle;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a flag that specifies whether an annotation is visible.
|
||
/// </summary>
|
||
/// <value>
|
||
/// <b>True</b> if the annotation is visible, <b>false</b> otherwise.
|
||
/// </value>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
DefaultValue(true),
|
||
SRDescription("DescriptionAttributeVisible"),
|
||
ParenthesizePropertyNameAttribute(true),
|
||
]
|
||
virtual public bool Visible
|
||
{
|
||
get
|
||
{
|
||
return _visible;
|
||
}
|
||
set
|
||
{
|
||
_visible = value;
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets an annotation's content alignment.
|
||
/// </summary>
|
||
/// <value>
|
||
/// A <see cref="ContentAlignment"/> value that represents the content alignment.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// This property is used to align text for <see cref="TextAnnotation"/>, <see cref="RectangleAnnotation"/>,
|
||
/// <see cref="EllipseAnnotation"/> and <see cref="CalloutAnnotation"/> objects, and to align
|
||
/// a non-scaled image inside an <see cref="ImageAnnotation"/> object.
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
DefaultValue(typeof(ContentAlignment), "MiddleCenter"),
|
||
SRDescription("DescriptionAttributeAlignment"),
|
||
]
|
||
virtual public ContentAlignment Alignment
|
||
{
|
||
get
|
||
{
|
||
return _alignment;
|
||
}
|
||
set
|
||
{
|
||
_alignment = value;
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the text color of an annotation.
|
||
/// <seealso cref="Font"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// A <see cref="Color"/> value used for the text color of an annotation.
|
||
/// </value>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
DefaultValue(typeof(Color), "Black"),
|
||
SRDescription("DescriptionAttributeForeColor"),
|
||
TypeConverter(typeof(ColorConverter)),
|
||
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base)
|
||
]
|
||
virtual public Color ForeColor
|
||
{
|
||
get
|
||
{
|
||
return _foreColor;
|
||
}
|
||
set
|
||
{
|
||
_foreColor = value;
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the font of an annotation's text.
|
||
/// <seealso cref="ForeColor"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// A <see cref="Font"/> object used for an annotation's text.
|
||
/// </value>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
DefaultValue(typeof(Font), "Microsoft Sans Serif, 8pt"),
|
||
SRDescription("DescriptionAttributeTextFont"),
|
||
]
|
||
virtual public Font Font
|
||
{
|
||
get
|
||
{
|
||
return _textFont;
|
||
}
|
||
set
|
||
{
|
||
_textFont = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <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>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
DefaultValue(typeof(TextStyle), "Default"),
|
||
SRDescription("DescriptionAttributeTextStyle"),
|
||
]
|
||
virtual public TextStyle TextStyle
|
||
{
|
||
get
|
||
{
|
||
return _textStyle;
|
||
}
|
||
set
|
||
{
|
||
_textStyle = value;
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the color of an annotation line.
|
||
/// <seealso cref="LineWidth"/>
|
||
/// <seealso cref="LineDashStyle"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// A <see cref="Color"/> value used to draw an annotation line.
|
||
/// </value>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
DefaultValue(typeof(Color), "Black"),
|
||
SRDescription("DescriptionAttributeLineColor"),
|
||
TypeConverter(typeof(ColorConverter)),
|
||
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base)
|
||
]
|
||
virtual public Color LineColor
|
||
{
|
||
get
|
||
{
|
||
return lineColor;
|
||
}
|
||
set
|
||
{
|
||
lineColor = value;
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the width of an annotation line.
|
||
/// <seealso cref="LineColor"/>
|
||
/// <seealso cref="LineDashStyle"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// An integer value defining the width of an annotation line in pixels.
|
||
/// </value>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
DefaultValue(1),
|
||
SRDescription("DescriptionAttributeLineWidth"),
|
||
]
|
||
virtual public int LineWidth
|
||
{
|
||
get
|
||
{
|
||
return _lineWidth;
|
||
}
|
||
set
|
||
{
|
||
if(value < 0)
|
||
{
|
||
throw (new ArgumentOutOfRangeException("value", SR.ExceptionAnnotationLineWidthIsNegative));
|
||
}
|
||
_lineWidth = value;
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the style of an annotation line.
|
||
/// <seealso cref="LineWidth"/>
|
||
/// <seealso cref="LineColor"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// A <see cref="ChartDashStyle"/> value used to draw an annotation line.
|
||
/// </value>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
DefaultValue(ChartDashStyle.Solid),
|
||
SRDescription("DescriptionAttributeLineDashStyle"),
|
||
]
|
||
virtual public ChartDashStyle LineDashStyle
|
||
{
|
||
get
|
||
{
|
||
return _lineDashStyle;
|
||
}
|
||
set
|
||
{
|
||
_lineDashStyle = value;
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the background color of an annotation.
|
||
/// <seealso cref="BackSecondaryColor"/>
|
||
/// <seealso cref="BackHatchStyle"/>
|
||
/// <seealso cref="BackGradientStyle"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// A <see cref="Color"/> value used for the background of an annotation.
|
||
/// </value>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
DefaultValue(typeof(Color), ""),
|
||
SRDescription("DescriptionAttributeBackColor"),
|
||
NotifyParentPropertyAttribute(true),
|
||
TypeConverter(typeof(ColorConverter)),
|
||
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base)
|
||
]
|
||
virtual public Color BackColor
|
||
{
|
||
get
|
||
{
|
||
return _backColor;
|
||
}
|
||
set
|
||
{
|
||
_backColor = value;
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the background hatch style of an annotation.
|
||
/// <seealso cref="BackSecondaryColor"/>
|
||
/// <seealso cref="BackColor"/>
|
||
/// <seealso cref="BackGradientStyle"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// A <see cref="ChartHatchStyle"/> value used for the background of an annotation.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// Two colors are used to draw the hatching, <see cref="BackColor"/> and <see cref="BackSecondaryColor"/>.
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
DefaultValue(ChartHatchStyle.None),
|
||
NotifyParentPropertyAttribute(true),
|
||
SRDescription("DescriptionAttributeBackHatchStyle"),
|
||
Editor(Editors.HatchStyleEditor.Editor, Editors.HatchStyleEditor.Base)
|
||
]
|
||
virtual public ChartHatchStyle BackHatchStyle
|
||
{
|
||
get
|
||
{
|
||
return _backHatchStyle;
|
||
}
|
||
set
|
||
{
|
||
_backHatchStyle = value;
|
||
Invalidate();
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// Gets or sets the background gradient style of an annotation.
|
||
/// <seealso cref="BackSecondaryColor"/>
|
||
/// <seealso cref="BackColor"/>
|
||
/// <seealso cref="BackHatchStyle"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// A <see cref="GradientStyle"/> value used for the background of an annotation.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// Two colors are used to draw the gradient, <see cref="BackColor"/> and <see cref="BackSecondaryColor"/>.
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
DefaultValue(GradientStyle.None),
|
||
NotifyParentPropertyAttribute(true),
|
||
SRDescription("DescriptionAttributeBackGradientStyle"),
|
||
Editor(Editors.GradientEditor.Editor, Editors.GradientEditor.Base)
|
||
]
|
||
virtual public GradientStyle BackGradientStyle
|
||
{
|
||
get
|
||
{
|
||
return _backGradientStyle;
|
||
}
|
||
set
|
||
{
|
||
_backGradientStyle = value;
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the secondary background color of an annotation.
|
||
/// <seealso cref="BackColor"/>
|
||
/// <seealso cref="BackHatchStyle"/>
|
||
/// <seealso cref="BackGradientStyle"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// A <see cref="Color"/> value used for the secondary color of an annotation background with
|
||
/// hatching or gradient fill.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// This color is used with <see cref="BackColor"/> when <see cref="BackHatchStyle"/> or
|
||
/// <see cref="BackGradientStyle"/> are used.
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
DefaultValue(typeof(Color), ""),
|
||
NotifyParentPropertyAttribute(true),
|
||
SRDescription("DescriptionAttributeBackSecondaryColor"),
|
||
TypeConverter(typeof(ColorConverter)),
|
||
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base)
|
||
]
|
||
virtual public Color BackSecondaryColor
|
||
{
|
||
get
|
||
{
|
||
return _backSecondaryColor;
|
||
}
|
||
set
|
||
{
|
||
_backSecondaryColor = value;
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the color of an annotation's shadow.
|
||
/// <seealso cref="ShadowOffset"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// A <see cref="Color"/> value used to draw an annotation's shadow.
|
||
/// </value>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
DefaultValue(typeof(Color), "128,0,0,0"),
|
||
SRDescription("DescriptionAttributeShadowColor"),
|
||
TypeConverter(typeof(ColorConverter)),
|
||
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base)
|
||
]
|
||
virtual public Color ShadowColor
|
||
{
|
||
get
|
||
{
|
||
return _shadowColor;
|
||
}
|
||
set
|
||
{
|
||
_shadowColor = value;
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the offset between an annotation and its shadow.
|
||
/// <seealso cref="ShadowColor"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// An integer value that represents the offset between an annotation and its shadow.
|
||
/// </value>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
DefaultValue(0),
|
||
SRDescription("DescriptionAttributeShadowOffset"),
|
||
]
|
||
virtual public int ShadowOffset
|
||
{
|
||
get
|
||
{
|
||
return _shadowOffset;
|
||
}
|
||
set
|
||
{
|
||
_shadowOffset = value;
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Axes Attaching
|
||
|
||
/// <summary>
|
||
/// Gets or sets the name of the X axis which an annotation is attached to.
|
||
/// </summary>
|
||
/// <value>
|
||
/// A string value that represents the name of the X axis which an annotation
|
||
/// is attached to.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// This property is for internal use and is hidden at design and run time.
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributeAnchorAxes"),
|
||
DefaultValue(""),
|
||
Browsable(false),
|
||
Bindable(false),
|
||
EditorBrowsableAttribute(EditorBrowsableState.Never),
|
||
SRDescription("DescriptionAttributeAxisXName"),
|
||
]
|
||
virtual public string AxisXName
|
||
{
|
||
get
|
||
{
|
||
if(_axisXName.Length == 0 && _axisX != null)
|
||
{
|
||
_axisXName = GetAxisName(_axisX);
|
||
}
|
||
return _axisXName;
|
||
}
|
||
set
|
||
{
|
||
_axisXName = value;
|
||
_axisX = null;
|
||
this.ResetCurrentRelativePosition();
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the name of the Y axis which an annotation is attached to.
|
||
/// </summary>
|
||
/// <value>
|
||
/// A string value that represents the name of the Y axis which an annotation
|
||
/// is attached to.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// This property is for internal use and is hidden at design and run time.
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributeAnchorAxes"),
|
||
Browsable(false),
|
||
Bindable(false),
|
||
EditorBrowsableAttribute(EditorBrowsableState.Never),
|
||
DefaultValue(""),
|
||
SRDescription("DescriptionAttributeAxisYName"),
|
||
SerializationVisibilityAttribute(SerializationVisibility.Hidden),
|
||
]
|
||
virtual public string AxisYName
|
||
{
|
||
get
|
||
{
|
||
// Always return empty string to prevent property serialization
|
||
// "YAxisName" property will be used instead.
|
||
return string.Empty;
|
||
}
|
||
set
|
||
{
|
||
this.YAxisName = value;
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Gets or sets the name of the Y axis which an annotation is attached to.
|
||
/// NOTE: "AxisYName" property was used before but the name was changed to solve the
|
||
/// duplicated hash value during the serialization with the "TitleSeparator" property.
|
||
/// </summary>
|
||
/// <value>
|
||
/// A string value that represents the name of the Y axis which an annotation
|
||
/// is attached to.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// This property is for internal use and is hidden at design and run time.
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributeAnchorAxes"),
|
||
Browsable(false),
|
||
Bindable(false),
|
||
EditorBrowsableAttribute(EditorBrowsableState.Never),
|
||
DefaultValue(""),
|
||
SRDescription("DescriptionAttributeAxisYName"),
|
||
]
|
||
virtual public string YAxisName
|
||
{
|
||
get
|
||
{
|
||
if(_axisYName.Length == 0 && _axisY != null)
|
||
{
|
||
_axisYName = GetAxisName(_axisY);
|
||
}
|
||
return _axisYName;
|
||
}
|
||
set
|
||
{
|
||
_axisYName = value;
|
||
_axisY = null;
|
||
this.ResetCurrentRelativePosition();
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the X axis which an annotation is attached to.
|
||
/// <seealso cref="AxisY"/>
|
||
/// <seealso cref="IsSizeAlwaysRelative"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// <see cref="Axis"/> object which an annotation is attached to.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// When an annotation is attached to an axis, its X position is always in
|
||
/// axis coordinates. To define an annotation's size in axis coordinates as well,
|
||
/// make sure the <see cref="IsSizeAlwaysRelative"/> property is set to <b>false</b>.
|
||
/// <para>
|
||
/// Set this value to <b>null</b> or <b>nothing</b> to disable attachment to the axis.
|
||
/// </para>
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributeAnchorAxes"),
|
||
DefaultValue(null),
|
||
DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
|
||
SerializationVisibilityAttribute(SerializationVisibility.Hidden),
|
||
SRDescription("DescriptionAttributeAxisX"),
|
||
Editor(Editors.AnnotationAxisUITypeEditor.Editor, Editors.AnnotationAxisUITypeEditor.Base),
|
||
TypeConverter(typeof(AnnotationAxisValueConverter)),
|
||
]
|
||
virtual public Axis AxisX
|
||
{
|
||
get
|
||
{
|
||
if(_axisX == null && _axisXName.Length > 0)
|
||
{
|
||
_axisX = GetAxisByName(_axisXName);
|
||
}
|
||
return _axisX;
|
||
}
|
||
set
|
||
{
|
||
_axisX = value;
|
||
_axisXName = String.Empty;
|
||
this.ResetCurrentRelativePosition();
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the Y axis which an annotation is attached to.
|
||
/// <seealso cref="AxisX"/>
|
||
/// <seealso cref="IsSizeAlwaysRelative"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// <see cref="Axis"/> object which an annotation is attached to.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// When an annotation is attached to an axis, its Y position is always in
|
||
/// axis coordinates. To define an annotation's size in axis coordinates as well,
|
||
/// make sure <see cref="IsSizeAlwaysRelative"/> property is set to <b>false</b>.
|
||
/// <para>
|
||
/// Set this value to <b>null</b> or <b>nothing</b> to disable annotation attachment to an axis.
|
||
/// </para>
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributeAnchorAxes"),
|
||
DefaultValue(null),
|
||
DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
|
||
SerializationVisibilityAttribute(SerializationVisibility.Hidden),
|
||
SRDescription("DescriptionAttributeAxisY"),
|
||
Editor(Editors.AnnotationAxisUITypeEditor.Editor, Editors.AnnotationAxisUITypeEditor.Base),
|
||
TypeConverter(typeof(AnnotationAxisValueConverter)),
|
||
]
|
||
virtual public Axis AxisY
|
||
{
|
||
get
|
||
{
|
||
if(_axisY == null && _axisYName.Length > 0)
|
||
{
|
||
_axisY = GetAxisByName(_axisYName);
|
||
}
|
||
return _axisY;
|
||
}
|
||
set
|
||
{
|
||
_axisY = value;
|
||
_axisYName = String.Empty;
|
||
this.ResetCurrentRelativePosition();
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Anchor
|
||
|
||
/// <summary>
|
||
/// Gets or sets the name of a data point which an annotation is anchored to.
|
||
/// </summary>
|
||
/// <value>
|
||
/// A string value that represents the name of the data point which an
|
||
/// annotation is anchored to.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// This property is for internal use and is hidden at design and run time.
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributeAnchor"),
|
||
Browsable(false),
|
||
Bindable(false),
|
||
EditorBrowsableAttribute(EditorBrowsableState.Never),
|
||
DefaultValue(""),
|
||
SRDescription("DescriptionAttributeAnchorDataPointName"),
|
||
]
|
||
virtual public string AnchorDataPointName
|
||
{
|
||
get
|
||
{
|
||
if(_anchorDataPointName.Length == 0 && _anchorDataPoint != null)
|
||
{
|
||
_anchorDataPointName = GetDataPointName(_anchorDataPoint);
|
||
}
|
||
return _anchorDataPointName;
|
||
}
|
||
set
|
||
{
|
||
_anchorDataPointName = value;
|
||
_anchorDataPoint = null;
|
||
this.ResetCurrentRelativePosition();
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the data point an annotation is anchored to.
|
||
/// <seealso cref="AnchorAlignment"/>
|
||
/// <seealso cref="AnchorOffsetX"/>
|
||
/// <seealso cref="AnchorOffsetY"/>
|
||
/// <seealso cref="AnchorX"/>
|
||
/// <seealso cref="AnchorY"/>
|
||
/// <seealso cref="SetAnchor(Charting.DataPoint)"/>
|
||
/// <seealso cref="SetAnchor(Charting.DataPoint, Charting.DataPoint)"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// A <see cref="DataPoint"/> object an annotation is anchored to.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// The annotation is anchored to the X and Y values of the specified data point,
|
||
/// and automatically uses the same axes coordinates as the data point.
|
||
/// <para>
|
||
/// To automatically position an annotation relative to an anchor point, make sure
|
||
/// its <see cref="X"/> and <see cref="Y"/> properties are set to <b>Double.NaN</b>.
|
||
/// The <see cref="AnchorAlignment"/> property may be used to change an annotation's
|
||
/// automatic position alignment to an anchor point. The <see cref="AnchorOffsetX"/> and
|
||
/// <see cref="AnchorOffsetY"/> properties may be used to add extra spacing.
|
||
/// </para>
|
||
/// <para>
|
||
/// When using this property, make sure the <see cref="AnchorX"/> and <see cref="AnchorY"/>
|
||
/// properties are set to <b>Double.NaN</b> (they have precedence).
|
||
/// </para>
|
||
/// <para>
|
||
/// Set this value to <b>null</b> or <b>nothing</b> to disable annotation anchoring to a data point.
|
||
/// </para>
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributeAnchor"),
|
||
DefaultValue(null),
|
||
DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
|
||
SerializationVisibilityAttribute(SerializationVisibility.Hidden),
|
||
SRDescription("DescriptionAttributeAnchorDataPoint"),
|
||
Editor(Editors.AnchorPointUITypeEditor.Editor, Editors.AnchorPointUITypeEditor.Base),
|
||
TypeConverter(typeof(AnchorPointValueConverter)),
|
||
]
|
||
virtual public DataPoint AnchorDataPoint
|
||
{
|
||
get
|
||
{
|
||
if(_anchorDataPoint == null && _anchorDataPointName.Length > 0)
|
||
{
|
||
_anchorDataPoint = GetDataPointByName(_anchorDataPointName);
|
||
}
|
||
return _anchorDataPoint;
|
||
}
|
||
set
|
||
{
|
||
_anchorDataPoint = value;
|
||
_anchorDataPointName = String.Empty;
|
||
this.ResetCurrentRelativePosition();
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the X coordinate the annotation is anchored to.
|
||
/// <seealso cref="AnchorY"/>
|
||
/// <seealso cref="AnchorOffsetX"/>
|
||
/// <seealso cref="AnchorOffsetY"/>
|
||
/// <seealso cref="AnchorAlignment"/>
|
||
/// <seealso cref="AnchorDataPoint"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// A double value that represents the X coordinate which an annotation is anchored to.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// The annotation is anchored to the X coordinate specified in relative or axis coordinates,
|
||
/// depending on the <see cref="AxisX"/> property value.
|
||
/// <para>
|
||
/// To automatically position an annotation relative to an anchor point, make sure
|
||
/// its <see cref="X"/> property is set to <b>Double.NaN</b>.
|
||
/// The <see cref="AnchorAlignment"/> property may be used to change the annotation's
|
||
/// automatic position alignment to the anchor point. The <see cref="AnchorOffsetX"/> and
|
||
/// <see cref="AnchorOffsetY"/> properties may be used to add extra spacing.
|
||
/// </para>
|
||
/// <para>
|
||
/// This property has a higher priority than the <see cref="AnchorDataPoint"/> property.
|
||
/// </para>
|
||
/// <para>
|
||
/// Set this value to <b>Double.NaN</b> to disable annotation anchoring to the value.
|
||
/// </para>
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributeAnchor"),
|
||
DefaultValue(double.NaN),
|
||
SRDescription("DescriptionAttributeAnchorX"),
|
||
RefreshPropertiesAttribute(RefreshProperties.All),
|
||
TypeConverter(typeof(DoubleNanValueConverter)),
|
||
]
|
||
virtual public double AnchorX
|
||
{
|
||
get
|
||
{
|
||
return _anchorX;
|
||
}
|
||
set
|
||
{
|
||
_anchorX = value;
|
||
this.ResetCurrentRelativePosition();
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the Y coordinate which an annotation is anchored to.
|
||
/// <seealso cref="AnchorY"/>
|
||
/// <seealso cref="AnchorOffsetX"/>
|
||
/// <seealso cref="AnchorOffsetY"/>
|
||
/// <seealso cref="AnchorAlignment"/>
|
||
/// <seealso cref="AnchorDataPoint"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// A double value that represents the Y coordinate which an annotation is anchored to.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// The annotation is anchored to the Y coordinate specified in relative or axis coordinates,
|
||
/// depending on the <see cref="AxisX"/> property value.
|
||
/// <para>
|
||
/// To automatically position an annotation relative to an anchor point, make sure
|
||
/// its <see cref="Y"/> property is set to <b>Double.NaN</b>.
|
||
/// The <see cref="AnchorAlignment"/> property may be used to change the annotation's
|
||
/// automatic position alignment to the anchor point. The <see cref="AnchorOffsetX"/> and
|
||
/// <see cref="AnchorOffsetY"/> properties may be used to add extra spacing.
|
||
/// </para>
|
||
/// <para>
|
||
/// This property has a higher priority than the <see cref="AnchorDataPoint"/> property.
|
||
/// </para>
|
||
/// <para>
|
||
/// Set this value to <b>Double.NaN</b> to disable annotation anchoring to the value.
|
||
/// </para>
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributeAnchor"),
|
||
DefaultValue(double.NaN),
|
||
SRDescription("DescriptionAttributeAnchorY"),
|
||
RefreshPropertiesAttribute(RefreshProperties.All),
|
||
TypeConverter(typeof(DoubleNanValueConverter)),
|
||
]
|
||
virtual public double AnchorY
|
||
{
|
||
get
|
||
{
|
||
return _anchorY;
|
||
}
|
||
set
|
||
{
|
||
_anchorY = value;
|
||
this.ResetCurrentRelativePosition();
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the x-coordinate offset between the positions of an annotation and its anchor point.
|
||
/// <seealso cref="AnchorOffsetY"/>
|
||
/// <seealso cref="AnchorDataPoint"/>
|
||
/// <seealso cref="AnchorX"/>
|
||
/// <seealso cref="AnchorAlignment"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// A double value that represents the x-coordinate offset between the positions of an annotation and its anchor point.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// The annotation must be anchored using the <see cref="AnchorDataPoint"/> or
|
||
/// <see cref="AnchorX"/> properties, and its <see cref="X"/> property must be set
|
||
/// to <b>Double.NaN</b>.
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributeAnchor"),
|
||
DefaultValue(0.0),
|
||
SRDescription("DescriptionAttributeAnchorOffsetX3"),
|
||
RefreshPropertiesAttribute(RefreshProperties.All),
|
||
]
|
||
virtual public double AnchorOffsetX
|
||
{
|
||
get
|
||
{
|
||
return anchorOffsetX;
|
||
}
|
||
set
|
||
{
|
||
if(value > 100.0 || value < -100.0)
|
||
{
|
||
throw (new ArgumentOutOfRangeException("value", SR.ExceptionAnnotationAnchorOffsetInvalid));
|
||
}
|
||
anchorOffsetX = value;
|
||
this.ResetCurrentRelativePosition();
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the y-coordinate offset between the positions of an annotation and its anchor point.
|
||
/// <seealso cref="Annotation.AnchorOffsetX"/>
|
||
/// <seealso cref="Annotation.AnchorDataPoint"/>
|
||
/// <seealso cref="Annotation.AnchorY"/>
|
||
/// <seealso cref="Annotation.AnchorAlignment"/>
|
||
/// </summary>
|
||
/// <value>
|
||
/// A double value that represents the y-coordinate offset between the positions of an annotation and its anchor point.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// Annotation must be anchored using <see cref="Annotation.AnchorDataPoint"/> or
|
||
/// <see cref="Annotation.AnchorY"/> properties and it's <see cref="Annotation.Y"/> property must be set
|
||
/// to <b>Double.NaN</b>.
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributeAnchor"),
|
||
DefaultValue(0.0),
|
||
SRDescription("DescriptionAttributeAnchorOffsetY3"),
|
||
RefreshPropertiesAttribute(RefreshProperties.All),
|
||
]
|
||
virtual public double AnchorOffsetY
|
||
{
|
||
get
|
||
{
|
||
return anchorOffsetY;
|
||
}
|
||
set
|
||
{
|
||
if(value > 100.0 || value < -100.0)
|
||
{
|
||
throw (new ArgumentOutOfRangeException("value", SR.ExceptionAnnotationAnchorOffsetInvalid));
|
||
}
|
||
anchorOffsetY = value;
|
||
this.ResetCurrentRelativePosition();
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets an annotation position's alignment to the anchor point.
|
||
/// <seealso cref="AnchorX"/>
|
||
/// <seealso cref="AnchorY"/>
|
||
/// <seealso cref="AnchorDataPoint"/>
|
||
/// <seealso cref="AnchorOffsetX"/>
|
||
/// <seealso cref="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="AnchorDataPoint"/>, or the <see cref="AnchorX"/>
|
||
/// and <see cref="AnchorY"/> properties. Its <see cref="X"/> and <see cref="Y"/>
|
||
/// properties must be set to <b>Double.NaN</b>.
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributeAnchor"),
|
||
DefaultValue(typeof(ContentAlignment), "BottomCenter"),
|
||
SRDescription("DescriptionAttributeAnchorAlignment"),
|
||
]
|
||
virtual public ContentAlignment AnchorAlignment
|
||
{
|
||
get
|
||
{
|
||
return anchorAlignment;
|
||
}
|
||
set
|
||
{
|
||
anchorAlignment = value;
|
||
this.ResetCurrentRelativePosition();
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
#endregion // Anchoring
|
||
|
||
#region Editing Permissions
|
||
|
||
#if Microsoft_CONTROL
|
||
|
||
/// <summary>
|
||
/// Gets or sets a flag that specifies whether an annotation may be selected
|
||
/// with a mouse by the end user.
|
||
/// </summary>
|
||
/// <value>
|
||
/// <b>True</b> if the annotation may be selected, <b>false</b> otherwise.
|
||
/// </value>
|
||
[
|
||
SRCategory("CategoryAttributeEditing"),
|
||
DefaultValue(false),
|
||
SRDescription("DescriptionAttributeAllowSelecting"),
|
||
]
|
||
virtual public bool AllowSelecting
|
||
{
|
||
get
|
||
{
|
||
return _allowSelecting;
|
||
}
|
||
set
|
||
{
|
||
_allowSelecting = value;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a flag that specifies whether an annotation may be moved
|
||
/// with a mouse by the end user.
|
||
/// </summary>
|
||
/// <value>
|
||
/// <b>True</b> if the annotation may be moved, <b>false</b> otherwise.
|
||
/// </value>
|
||
[
|
||
SRCategory("CategoryAttributeEditing"),
|
||
DefaultValue(false),
|
||
SRDescription("DescriptionAttributeAllowMoving"),
|
||
]
|
||
virtual public bool AllowMoving
|
||
{
|
||
get
|
||
{
|
||
return _allowMoving;
|
||
}
|
||
set
|
||
{
|
||
_allowMoving = value;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a flag that specifies whether an annotation anchor may be moved
|
||
/// with a mouse by the end user.
|
||
/// </summary>
|
||
/// <value>
|
||
/// <b>True</b> if the annotation anchor may be moved, <b>false</b> otherwise.
|
||
/// </value>
|
||
[
|
||
SRCategory("CategoryAttributeEditing"),
|
||
DefaultValue(false),
|
||
SRDescription("DescriptionAttributeAllowAnchorMoving3"),
|
||
]
|
||
virtual public bool AllowAnchorMoving
|
||
{
|
||
get
|
||
{
|
||
return _allowAnchorMoving;
|
||
}
|
||
set
|
||
{
|
||
_allowAnchorMoving = value;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a flag that specifies whether an annotation may be resized
|
||
/// with a mouse by the end user.
|
||
/// </summary>
|
||
/// <value>
|
||
/// <b>True</b> if the annotation may be resized, <b>false</b> otherwise.
|
||
/// </value>
|
||
[
|
||
SRCategory("CategoryAttributeEditing"),
|
||
DefaultValue(false),
|
||
SRDescription("DescriptionAttributeAllowResizing"),
|
||
]
|
||
virtual public bool AllowResizing
|
||
{
|
||
get
|
||
{
|
||
return _allowResizing;
|
||
}
|
||
set
|
||
{
|
||
_allowResizing = value;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a flag that specifies whether an annotation's text may be edited
|
||
/// when the end user double clicks on the text.
|
||
/// </summary>
|
||
/// <value>
|
||
/// <b>True</b> if the annotation text may be edited, <b>false</b> otherwise.
|
||
/// </value>
|
||
[
|
||
SRCategory("CategoryAttributeEditing"),
|
||
DefaultValue(false),
|
||
SRDescription("DescriptionAttributeAllowTextEditing"),
|
||
]
|
||
virtual public bool AllowTextEditing
|
||
{
|
||
get
|
||
{
|
||
return _allowTextEditing;
|
||
}
|
||
set
|
||
{
|
||
_allowTextEditing = value;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a flag that specifies whether a polygon annotation's points
|
||
/// may be moved with a mouse by the end user.
|
||
/// </summary>
|
||
/// <value>
|
||
/// <b>True</b> if the polygon annotation's points may be moved, <b>false</b> otherwise.
|
||
/// </value>
|
||
[
|
||
SRCategory("CategoryAttributeEditing"),
|
||
DefaultValue(false),
|
||
SRDescription("DescriptionAttributeAllowPathEditing3"),
|
||
]
|
||
virtual public bool AllowPathEditing
|
||
{
|
||
get
|
||
{
|
||
return _allowPathEditing;
|
||
}
|
||
set
|
||
{
|
||
_allowPathEditing = value;
|
||
}
|
||
}
|
||
|
||
#endif // Microsoft_CONTROL
|
||
|
||
#endregion
|
||
|
||
#region Interactivity
|
||
|
||
/// <summary>
|
||
/// Gets or sets an annotation's tooltip text.
|
||
/// </summary>
|
||
/// <value>
|
||
/// A string value.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// Special keywords can be used in the text when an annotation is anchored to
|
||
/// a data point using the <see cref="AnchorDataPoint"/> property. For a listing of
|
||
/// these keywords, refer to the "Annotations" help topic.
|
||
/// </remarks>
|
||
[
|
||
|
||
SRCategory("CategoryAttributeMisc"),
|
||
DefaultValue(""),
|
||
SRDescription("DescriptionAttributeToolTip"),
|
||
]
|
||
virtual public string ToolTip
|
||
{
|
||
get
|
||
{
|
||
return _tooltip;
|
||
}
|
||
set
|
||
{
|
||
_tooltip = value;
|
||
|
||
}
|
||
}
|
||
|
||
#if !Microsoft_CONTROL
|
||
|
||
/// <summary>
|
||
/// Gets or sets an annotation's Url.
|
||
/// </summary>
|
||
/// <value>
|
||
/// A string value.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// Special keywords can be used when an annotation is anchored to
|
||
/// a data point using the <see cref="AnchorDataPoint"/> property. For a listing of
|
||
/// these keywords, refer to the "Annotations" help topic.
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributeMisc"),
|
||
DefaultValue(""),
|
||
SRDescription("DescriptionAttributeUrl"),
|
||
]
|
||
virtual public string Url
|
||
{
|
||
get
|
||
{
|
||
return _url;
|
||
}
|
||
set
|
||
{
|
||
_url = value;
|
||
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets an annotation's map area attributes.
|
||
/// </summary>
|
||
/// <value>
|
||
/// A string value.
|
||
/// </value>
|
||
/// <remarks>
|
||
/// This string will be added to the attributes of the image map generated
|
||
/// for the annotation.
|
||
/// <para>
|
||
/// Special keywords can be used when an annotation is anchored to
|
||
/// a data point using the <see cref="AnchorDataPoint"/> property. For a listing of
|
||
/// these keywords, refer to the "Annotations" help topic.
|
||
/// </para>
|
||
/// </remarks>
|
||
[
|
||
SRCategory("CategoryAttributeMisc"),
|
||
DefaultValue(""),
|
||
SRDescription("DescriptionAttributeMapAreaAttributes"),
|
||
]
|
||
virtual public string MapAreaAttributes
|
||
{
|
||
get
|
||
{
|
||
return _mapAreaAttributes;
|
||
}
|
||
set
|
||
{
|
||
_mapAreaAttributes = value;
|
||
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the postback value which can be processed on click event.
|
||
/// </summary>
|
||
/// <value>The value which is passed to click event as argument.</value>
|
||
[DefaultValue("")]
|
||
[SRCategory(SR.Keys.CategoryAttributeMapArea)]
|
||
[SRDescription(SR.Keys.DescriptionAttributePostBackValue)]
|
||
public string PostBackValue
|
||
{
|
||
get
|
||
{
|
||
return this._postbackValue;
|
||
}
|
||
set
|
||
{
|
||
this._postbackValue = value;
|
||
}
|
||
}
|
||
|
||
|
||
#endif // !Microsoft_CONTROL
|
||
|
||
#endregion // Interactivity
|
||
|
||
#endregion
|
||
|
||
#region Methods
|
||
|
||
#region Painting
|
||
|
||
/// <summary>
|
||
/// Paints the annotation object using the specified graphics.
|
||
/// </summary>
|
||
/// <param name="graphics">
|
||
/// A <see cref="ChartGraphics"/> object used to paint the annotation object.
|
||
/// </param>
|
||
/// <param name="chart">
|
||
/// Reference to the annotation's <see cref="Chart"/> control owner.
|
||
/// </param>
|
||
abstract internal void Paint(Chart chart, ChartGraphics graphics);
|
||
|
||
/// <summary>
|
||
/// Paints annotation selection markers.
|
||
/// </summary>
|
||
/// <param name="chartGraphics">Chart graphics used for painting.</param>
|
||
/// <param name="rect">Selection rectangle.</param>
|
||
/// <param name="path">Selection path.</param>
|
||
virtual internal void PaintSelectionHandles(ChartGraphics chartGraphics, RectangleF rect, GraphicsPath path)
|
||
{
|
||
// Define markers appearance style
|
||
Color markerBorderColor = Color.Black;
|
||
Color markerColor = Color.FromArgb(200, 255, 255, 255);
|
||
MarkerStyle markerStyle = MarkerStyle.Square;
|
||
int markerSize = selectionMarkerSize;
|
||
Boolean selected = this.IsSelected;
|
||
|
||
SizeF markerSizeRel = chartGraphics.GetRelativeSize(new SizeF(markerSize, markerSize));
|
||
if (this.Common.ProcessModePaint &&
|
||
!this.Common.ChartPicture.isPrinting)
|
||
{
|
||
// Clear selection rectangles
|
||
this.selectionRects = null;
|
||
|
||
// Check if annotation is selected
|
||
if (selected)
|
||
{
|
||
// Create selection rectangles
|
||
this.selectionRects = new RectangleF[9];
|
||
|
||
// Draw selection handles for single dimension annotations like line.
|
||
if(this.SelectionPointsStyle == SelectionPointsStyle.TwoPoints)
|
||
{
|
||
// Save selection handles position in array elements 0 and 4
|
||
this.selectionRects[(int)ResizingMode.TopLeftHandle] = new RectangleF(
|
||
rect.X - markerSizeRel.Width/2f,
|
||
rect.Y - markerSizeRel.Height/2f,
|
||
markerSizeRel.Width,
|
||
markerSizeRel.Height);
|
||
this.selectionRects[(int)ResizingMode.BottomRightHandle] = new RectangleF(
|
||
rect.Right - markerSizeRel.Width/2f,
|
||
rect.Bottom - markerSizeRel.Height/2f,
|
||
markerSizeRel.Width,
|
||
markerSizeRel.Height);
|
||
|
||
|
||
// Draw selection handle
|
||
chartGraphics.DrawMarkerRel(
|
||
rect.Location,
|
||
markerStyle,
|
||
markerSize,
|
||
markerColor,
|
||
markerBorderColor,
|
||
1,
|
||
"",
|
||
Color.Empty,
|
||
0,
|
||
Color.FromArgb(128, 0, 0, 0),
|
||
RectangleF.Empty);
|
||
|
||
chartGraphics.DrawMarkerRel(
|
||
new PointF(rect.Right, rect.Bottom),
|
||
markerStyle,
|
||
markerSize,
|
||
markerColor,
|
||
markerBorderColor,
|
||
1,
|
||
"",
|
||
Color.Empty,
|
||
0,
|
||
Color.FromArgb(128, 0, 0, 0),
|
||
RectangleF.Empty);
|
||
}
|
||
else if(this.SelectionPointsStyle == SelectionPointsStyle.Rectangle)
|
||
{
|
||
for(int index = 0; index < 8; index++)
|
||
{
|
||
// Get handle position
|
||
PointF handlePosition = PointF.Empty;
|
||
switch((ResizingMode)index)
|
||
{
|
||
case ResizingMode.TopLeftHandle:
|
||
handlePosition = rect.Location;
|
||
break;
|
||
case ResizingMode.TopHandle:
|
||
handlePosition = new PointF(rect.X + rect.Width / 2f, rect.Y);
|
||
break;
|
||
case ResizingMode.TopRightHandle:
|
||
handlePosition = new PointF(rect.Right, rect.Y);
|
||
break;
|
||
case ResizingMode.RightHandle:
|
||
handlePosition = new PointF(rect.Right, rect.Y + rect.Height / 2f);
|
||
break;
|
||
case ResizingMode.BottomRightHandle:
|
||
handlePosition = new PointF(rect.Right, rect.Bottom);
|
||
break;
|
||
case ResizingMode.BottomHandle:
|
||
handlePosition = new PointF(rect.X + rect.Width / 2f, rect.Bottom);
|
||
break;
|
||
case ResizingMode.BottomLeftHandle:
|
||
handlePosition = new PointF(rect.X, rect.Bottom);
|
||
break;
|
||
case ResizingMode.LeftHandle:
|
||
handlePosition = new PointF(rect.X, rect.Y + rect.Height / 2f);
|
||
break;
|
||
}
|
||
|
||
// Save selection handles position in array elements 0 and 4
|
||
this.selectionRects[index] = new RectangleF(
|
||
handlePosition.X - markerSizeRel.Width/2f,
|
||
handlePosition.Y - markerSizeRel.Height/2f,
|
||
markerSizeRel.Width,
|
||
markerSizeRel.Height);
|
||
|
||
// Draw selection handle
|
||
chartGraphics.DrawMarkerRel(
|
||
handlePosition,
|
||
markerStyle,
|
||
markerSize,
|
||
markerColor,
|
||
markerBorderColor,
|
||
1,
|
||
"",
|
||
Color.Empty,
|
||
0,
|
||
Color.FromArgb(128, 0, 0, 0),
|
||
RectangleF.Empty);
|
||
}
|
||
}
|
||
|
||
|
||
//********************************************************************
|
||
//** Draw anchor selection handle
|
||
//********************************************************************
|
||
|
||
// Get vertical and horizontal axis
|
||
Axis vertAxis = null;
|
||
Axis horizAxis = null;
|
||
GetAxes(ref vertAxis, ref horizAxis);
|
||
|
||
// Get anchor position
|
||
double anchorX = double.NaN;
|
||
double anchorY = double.NaN;
|
||
bool relativeX = false;
|
||
bool relativeY = false;
|
||
this.GetAnchorLocation(ref anchorX, ref anchorY, ref relativeX, ref relativeY);
|
||
|
||
// Convert anchor location to relative coordinates
|
||
if(!double.IsNaN(anchorX) && !double.IsNaN(anchorY))
|
||
{
|
||
if( !relativeX && horizAxis != null )
|
||
{
|
||
anchorX = horizAxis.ValueToPosition(anchorX);
|
||
}
|
||
if( !relativeY && vertAxis != null )
|
||
{
|
||
anchorY = vertAxis.ValueToPosition(anchorY);
|
||
}
|
||
|
||
// Apply 3D transforamtion if required
|
||
ChartArea chartArea = null;
|
||
if(horizAxis != null && horizAxis.ChartArea != null)
|
||
{
|
||
chartArea = horizAxis.ChartArea;
|
||
}
|
||
if(vertAxis != null && vertAxis.ChartArea != null)
|
||
{
|
||
chartArea = vertAxis.ChartArea;
|
||
}
|
||
if(chartArea != null &&
|
||
chartArea.Area3DStyle.Enable3D == true &&
|
||
!chartArea.chartAreaIsCurcular &&
|
||
chartArea.requireAxes &&
|
||
chartArea.matrix3D.IsInitialized())
|
||
{
|
||
// Get anotation Z coordinate (use scene depth or anchored point Z position)
|
||
float positionZ = chartArea.areaSceneDepth;
|
||
if (this.AnchorDataPoint != null && this.AnchorDataPoint.series != null)
|
||
{
|
||
float depth = 0f;
|
||
chartArea.GetSeriesZPositionAndDepth(
|
||
this.AnchorDataPoint.series,
|
||
out depth,
|
||
out positionZ);
|
||
positionZ += depth / 2f;
|
||
}
|
||
|
||
// Define 3D points of annotation object
|
||
Point3D[] annot3DPoints = new Point3D[1];
|
||
annot3DPoints[0] = new Point3D((float)anchorX, (float)anchorY, positionZ);
|
||
|
||
// Tranform cube coordinates
|
||
chartArea.matrix3D.TransformPoints(annot3DPoints);
|
||
|
||
// Get transformed coordinates
|
||
anchorX = annot3DPoints[0].X;
|
||
anchorY = annot3DPoints[0].Y;
|
||
}
|
||
|
||
// Save selection handles position in array elements 0 and 4
|
||
this.selectionRects[(int)ResizingMode.AnchorHandle] = new RectangleF(
|
||
(float)anchorX - markerSizeRel.Width/2f,
|
||
(float)anchorY - markerSizeRel.Height/2f,
|
||
markerSizeRel.Width,
|
||
markerSizeRel.Height);
|
||
|
||
// Draw circular selection handle
|
||
chartGraphics.DrawMarkerRel(
|
||
new PointF((float)anchorX, (float)anchorY),
|
||
MarkerStyle.Cross,
|
||
selectionMarkerSize + 3,
|
||
markerColor,
|
||
markerBorderColor,
|
||
1,
|
||
"",
|
||
Color.Empty,
|
||
0,
|
||
Color.FromArgb(128, 0, 0, 0),
|
||
RectangleF.Empty);
|
||
}
|
||
|
||
#if Microsoft_CONTROL
|
||
|
||
//********************************************************************
|
||
//** Draw path selection handles
|
||
//********************************************************************
|
||
if(path != null && AllowPathEditing)
|
||
{
|
||
// Create selection rectangles for each point
|
||
PointF[] pathPoints = path.PathPoints;
|
||
RectangleF[] newSelectionRects = new RectangleF[pathPoints.Length + 9];
|
||
|
||
// Copy previous rectangles (first nine elements)
|
||
for(int index = 0; index < this.selectionRects.Length; index++)
|
||
{
|
||
newSelectionRects[index] = this.selectionRects[index];
|
||
}
|
||
this.selectionRects = newSelectionRects;
|
||
|
||
// Loop through all points
|
||
for(int index = 0; index < pathPoints.Length; index++)
|
||
{
|
||
// Get handle position
|
||
PointF handlePosition = chartGraphics.GetRelativePoint(pathPoints[index]);
|
||
|
||
// Save selection handles position in array elements 0 and 4
|
||
this.selectionRects[9 + index] = new RectangleF(
|
||
handlePosition.X - markerSizeRel.Width/2f,
|
||
handlePosition.Y - markerSizeRel.Height/2f,
|
||
markerSizeRel.Width,
|
||
markerSizeRel.Height);
|
||
|
||
// Draw selection handle
|
||
chartGraphics.DrawMarkerRel(
|
||
handlePosition,
|
||
MarkerStyle.Circle,
|
||
selectionMarkerSize + 1,
|
||
markerColor,
|
||
markerBorderColor,
|
||
1,
|
||
"",
|
||
Color.Empty,
|
||
0,
|
||
Color.FromArgb(128, 0, 0, 0),
|
||
RectangleF.Empty);
|
||
}
|
||
}
|
||
|
||
#endif // Microsoft_CONTROL
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Position and Size
|
||
|
||
/// <summary>
|
||
/// Resizes an annotation according to its content size.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Sets the annotation width and height to fit the specified text. This method applies to
|
||
/// <see cref="TextAnnotation"/>, <see cref="RectangleAnnotation"/>, <see cref="EllipseAnnotation"/>
|
||
/// and <see cref="CalloutAnnotation"/> objects only.
|
||
/// </remarks>
|
||
virtual public void ResizeToContent()
|
||
{
|
||
RectangleF position = GetContentPosition();
|
||
if(!double.IsNaN(position.Width))
|
||
{
|
||
this.Width = position.Width;
|
||
}
|
||
if(!double.IsNaN(position.Height))
|
||
{
|
||
this.Height = position.Height;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets an annotation's content position.
|
||
/// </summary>
|
||
/// <returns>Annotation's content size.</returns>
|
||
virtual internal RectangleF GetContentPosition()
|
||
{
|
||
return new RectangleF(float.NaN, float.NaN, float.NaN, float.NaN);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets an annotation's anchor point location.
|
||
/// </summary>
|
||
/// <param name="anchorX">Returns the anchor X coordinate.</param>
|
||
/// <param name="anchorY">Returns the anchor Y coordinate.</param>
|
||
/// <param name="inRelativeAnchorX">Indicates if X coordinate is in relative chart coordinates.</param>
|
||
/// <param name="inRelativeAnchorY">Indicates if Y coordinate is in relative chart coordinates.</param>
|
||
private void GetAnchorLocation(ref double anchorX, ref double anchorY, ref bool inRelativeAnchorX, ref bool inRelativeAnchorY)
|
||
{
|
||
anchorX = this.AnchorX;
|
||
anchorY = this.AnchorY;
|
||
|
||
if(this.AnchorDataPoint != null &&
|
||
this.AnchorDataPoint.series != null &&
|
||
this.Chart != null &&
|
||
this.Chart.chartPicture != null)
|
||
{
|
||
// Anchor data point is not allowed for gropped annotations
|
||
if(this.AnnotationGroup != null)
|
||
{
|
||
throw (new InvalidOperationException(SR.ExceptionAnnotationGroupedAnchorDataPointMustBeEmpty));
|
||
}
|
||
|
||
// Get data point relative coordinate
|
||
if( double.IsNaN(anchorX) || double.IsNaN(anchorY))
|
||
{
|
||
// Get X value from data point
|
||
if( double.IsNaN(anchorX) )
|
||
{
|
||
anchorX = this.AnchorDataPoint.positionRel.X;
|
||
inRelativeAnchorX = true;
|
||
}
|
||
|
||
// Get Y value from data point
|
||
if( double.IsNaN(anchorY) )
|
||
{
|
||
anchorY = this.AnchorDataPoint.positionRel.Y;
|
||
inRelativeAnchorY = true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets annotation object position in relative coordinates.
|
||
/// </summary>
|
||
/// <param name="location">Returns annotation location.</param>
|
||
/// <param name="size">Returns annotation size.</param>
|
||
/// <param name="anchorLocation">Returns annotation anchor point location.</param>
|
||
virtual internal void GetRelativePosition(out PointF location, out SizeF size, out PointF anchorLocation)
|
||
{
|
||
bool saveCurrentPosition = true;
|
||
|
||
//***********************************************************************
|
||
//** Check if position was precalculated
|
||
//***********************************************************************
|
||
if(!double.IsNaN(currentPositionRel.X) && !double.IsNaN(currentPositionRel.X))
|
||
{
|
||
location = currentPositionRel.Location;
|
||
size = currentPositionRel.Size;
|
||
anchorLocation = currentAnchorLocationRel;
|
||
return;
|
||
}
|
||
|
||
//***********************************************************************
|
||
//** Get vertical and horizontal axis
|
||
//***********************************************************************
|
||
Axis vertAxis = null;
|
||
Axis horizAxis = null;
|
||
GetAxes(ref vertAxis, ref horizAxis);
|
||
|
||
//***********************************************************************
|
||
//** Check if annotation was anchored to 2 points.
|
||
//***********************************************************************
|
||
if(this._anchorDataPoint != null &&
|
||
this._anchorDataPoint2 != null)
|
||
{
|
||
// Annotation size is in axis coordinates
|
||
this.IsSizeAlwaysRelative = false;
|
||
|
||
// Set annotation size
|
||
this.Height =
|
||
vertAxis.PositionToValue(this._anchorDataPoint2.positionRel.Y, false) -
|
||
vertAxis.PositionToValue(this._anchorDataPoint.positionRel.Y, false);
|
||
this.Width =
|
||
horizAxis.PositionToValue(this._anchorDataPoint2.positionRel.X, false) -
|
||
horizAxis.PositionToValue(this._anchorDataPoint.positionRel.X, false);
|
||
|
||
// Reset second anchor point after setting width and height
|
||
this._anchorDataPoint2 = null;
|
||
}
|
||
|
||
//***********************************************************************
|
||
//** Flags which indicate that coordinate was already transformed
|
||
//** into chart relative coordinate system.
|
||
//***********************************************************************
|
||
bool inRelativeX = false;
|
||
bool inRelativeY = false;
|
||
bool inRelativeWidth = (_isSizeAlwaysRelative) ? true : false;
|
||
bool inRelativeHeight = (_isSizeAlwaysRelative) ? true : false;
|
||
bool inRelativeAnchorX = false;
|
||
bool inRelativeAnchorY = false;
|
||
|
||
//***********************************************************************
|
||
//** Get anchoring coordinates from anchored Data Point.
|
||
//***********************************************************************
|
||
double anchorX = this.AnchorX;
|
||
double anchorY = this.AnchorY;
|
||
GetAnchorLocation(ref anchorX, ref anchorY, ref inRelativeAnchorX, ref inRelativeAnchorY);
|
||
|
||
//***********************************************************************
|
||
//** Calculate scaling and translation for the annotations in the group.
|
||
//***********************************************************************
|
||
AnnotationGroup group = this.AnnotationGroup;
|
||
PointF groupLocation = PointF.Empty;
|
||
double groupScaleX = 1.0;
|
||
double groupScaleY = 1.0;
|
||
if(group != null)
|
||
{
|
||
// Do not save relative position of annotations inside the group
|
||
saveCurrentPosition = false;
|
||
|
||
// Take relative position of the group
|
||
SizeF groupSize = SizeF.Empty;
|
||
PointF groupAnchorLocation = PointF.Empty;
|
||
group.GetRelativePosition(out groupLocation, out groupSize, out groupAnchorLocation);
|
||
|
||
// Calculate Scale
|
||
groupScaleX = groupSize.Width / 100.0;
|
||
groupScaleY = groupSize.Height / 100.0;
|
||
}
|
||
|
||
|
||
//***********************************************************************
|
||
//** Get annotation automatic size.
|
||
//***********************************************************************
|
||
double relativeWidth = this._width;
|
||
double relativeHeight = this._height;
|
||
|
||
// Get annotation content position
|
||
RectangleF contentPosition = GetContentPosition();
|
||
|
||
// Set annotation size if not set to custom value
|
||
if( double.IsNaN(relativeWidth) )
|
||
{
|
||
relativeWidth = contentPosition.Width;
|
||
inRelativeWidth = true;
|
||
}
|
||
else
|
||
{
|
||
relativeWidth *= groupScaleX;
|
||
}
|
||
if( double.IsNaN(relativeHeight) )
|
||
{
|
||
relativeHeight = contentPosition.Height;
|
||
inRelativeHeight = true;
|
||
}
|
||
else
|
||
{
|
||
relativeHeight *= groupScaleY;
|
||
}
|
||
|
||
//***********************************************************************
|
||
//** Provide "dummy" size at design time
|
||
//***********************************************************************
|
||
if(this.Chart != null && this.Chart.IsDesignMode())
|
||
{
|
||
if(this.IsSizeAlwaysRelative ||
|
||
(vertAxis == null && horizAxis == null) )
|
||
{
|
||
if(double.IsNaN(relativeWidth))
|
||
{
|
||
relativeWidth = 20.0;
|
||
saveCurrentPosition = false;
|
||
}
|
||
if(double.IsNaN(relativeHeight))
|
||
{
|
||
relativeHeight = 20.0;
|
||
saveCurrentPosition = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
//***********************************************************************
|
||
//** Get annotation location.
|
||
//***********************************************************************
|
||
double relativeX = this.X;
|
||
double relativeY = this.Y;
|
||
|
||
// Check if annotation location Y coordinate is defined
|
||
if( double.IsNaN(relativeY) && !double.IsNaN(anchorY) )
|
||
{
|
||
inRelativeY = true;
|
||
double relativeAnchorY = anchorY;
|
||
if(!inRelativeAnchorY && vertAxis != null)
|
||
{
|
||
relativeAnchorY = vertAxis.ValueToPosition(anchorY);
|
||
}
|
||
if(this.AnchorAlignment == ContentAlignment.TopCenter ||
|
||
this.AnchorAlignment == ContentAlignment.TopLeft ||
|
||
this.AnchorAlignment == ContentAlignment.TopRight)
|
||
{
|
||
relativeY = relativeAnchorY + this.AnchorOffsetY;
|
||
relativeY *= groupScaleY;
|
||
}
|
||
else if(this.AnchorAlignment == ContentAlignment.BottomCenter ||
|
||
this.AnchorAlignment == ContentAlignment.BottomLeft ||
|
||
this.AnchorAlignment == ContentAlignment.BottomRight)
|
||
{
|
||
relativeY = relativeAnchorY - this.AnchorOffsetY;
|
||
relativeY *= groupScaleY;
|
||
if(relativeHeight != 0f && !double.IsNaN(relativeHeight))
|
||
{
|
||
if(inRelativeHeight)
|
||
{
|
||
relativeY -= relativeHeight;
|
||
}
|
||
else if(vertAxis != null)
|
||
{
|
||
float yValue = (float)vertAxis.PositionToValue(relativeY);
|
||
float bottomRel = (float)vertAxis.ValueToPosition(yValue + relativeHeight);
|
||
relativeY -= bottomRel - relativeY;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
relativeY = relativeAnchorY + this.AnchorOffsetY;
|
||
relativeY *= groupScaleY;
|
||
if(relativeHeight != 0f && !double.IsNaN(relativeHeight))
|
||
{
|
||
if(inRelativeHeight)
|
||
{
|
||
relativeY -= relativeHeight/2f;
|
||
}
|
||
else if(vertAxis != null)
|
||
{
|
||
float yValue = (float)vertAxis.PositionToValue(relativeY);
|
||
float bottomRel = (float)vertAxis.ValueToPosition(yValue + relativeHeight);
|
||
relativeY -= (bottomRel - relativeY) / 2f;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
relativeY *= groupScaleY;
|
||
}
|
||
|
||
// Check if annotation location X coordinate is defined
|
||
if( double.IsNaN(relativeX) && !double.IsNaN(anchorX) )
|
||
{
|
||
inRelativeX = true;
|
||
double relativeAnchorX = anchorX;
|
||
if(!inRelativeAnchorX && horizAxis != null)
|
||
{
|
||
relativeAnchorX = horizAxis.ValueToPosition(anchorX);
|
||
}
|
||
if(this.AnchorAlignment == ContentAlignment.BottomLeft ||
|
||
this.AnchorAlignment == ContentAlignment.MiddleLeft ||
|
||
this.AnchorAlignment == ContentAlignment.TopLeft)
|
||
{
|
||
relativeX = relativeAnchorX + this.AnchorOffsetX;
|
||
relativeX *= groupScaleX;
|
||
}
|
||
else if(this.AnchorAlignment == ContentAlignment.BottomRight ||
|
||
this.AnchorAlignment == ContentAlignment.MiddleRight ||
|
||
this.AnchorAlignment == ContentAlignment.TopRight)
|
||
{
|
||
relativeX = relativeAnchorX - this.AnchorOffsetX;
|
||
relativeX *= groupScaleX;
|
||
if(relativeWidth != 0f && !double.IsNaN(relativeWidth))
|
||
{
|
||
if(inRelativeWidth)
|
||
{
|
||
relativeX -= relativeWidth;
|
||
}
|
||
else if(horizAxis != null)
|
||
{
|
||
float xValue = (float)horizAxis.PositionToValue(relativeX);
|
||
relativeX -= horizAxis.ValueToPosition(xValue + relativeWidth) - relativeX;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
relativeX = relativeAnchorX + this.AnchorOffsetX;
|
||
relativeX *= groupScaleX;
|
||
if(relativeWidth != 0f && !double.IsNaN(relativeWidth))
|
||
{
|
||
if(inRelativeWidth)
|
||
{
|
||
relativeX -= relativeWidth/2f;
|
||
}
|
||
else if(horizAxis != null)
|
||
{
|
||
float xValue = (float)horizAxis.PositionToValue(relativeX);
|
||
relativeX -= (horizAxis.ValueToPosition(xValue + relativeWidth) - relativeX) / 2f;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
relativeX *= groupScaleX;
|
||
}
|
||
|
||
// Translate
|
||
relativeX += groupLocation.X;
|
||
relativeY += groupLocation.Y;
|
||
|
||
//***********************************************************************
|
||
//** Get annotation automatic location.
|
||
//***********************************************************************
|
||
|
||
// Set annotation size if not set to custom value
|
||
if( double.IsNaN(relativeX) )
|
||
{
|
||
relativeX = contentPosition.X * groupScaleX;
|
||
inRelativeX = true;
|
||
}
|
||
if( double.IsNaN(relativeY) )
|
||
{
|
||
relativeY = contentPosition.Y * groupScaleY;
|
||
inRelativeY = true;
|
||
}
|
||
|
||
//***********************************************************************
|
||
//** Convert coordinates from axes values to relative coordinates.
|
||
//***********************************************************************
|
||
|
||
// Check if values are set in axis values
|
||
if(horizAxis != null)
|
||
{
|
||
if(!inRelativeX)
|
||
{
|
||
relativeX = horizAxis.ValueToPosition(relativeX);
|
||
}
|
||
if(!inRelativeAnchorX)
|
||
{
|
||
anchorX = horizAxis.ValueToPosition(anchorX);
|
||
}
|
||
if(!inRelativeWidth)
|
||
{
|
||
relativeWidth = horizAxis.ValueToPosition(
|
||
horizAxis.PositionToValue(relativeX, false) + relativeWidth) - relativeX;
|
||
}
|
||
}
|
||
if(vertAxis != null)
|
||
{
|
||
if(!inRelativeY)
|
||
{
|
||
relativeY = vertAxis.ValueToPosition(relativeY);
|
||
}
|
||
if(!inRelativeAnchorY)
|
||
{
|
||
anchorY = vertAxis.ValueToPosition(anchorY);
|
||
}
|
||
if(!inRelativeHeight)
|
||
{
|
||
relativeHeight = vertAxis.ValueToPosition(
|
||
vertAxis.PositionToValue(relativeY, false) + relativeHeight) - relativeY;
|
||
}
|
||
}
|
||
bool isTextAnnotation = this is TextAnnotation;
|
||
//***********************************************************************
|
||
//** Apply 3D transforamtion if required
|
||
//***********************************************************************
|
||
ChartArea chartArea = null;
|
||
if(horizAxis != null && horizAxis.ChartArea != null)
|
||
{
|
||
chartArea = horizAxis.ChartArea;
|
||
}
|
||
if(vertAxis != null && vertAxis.ChartArea != null)
|
||
{
|
||
chartArea = vertAxis.ChartArea;
|
||
}
|
||
if(chartArea != null &&
|
||
chartArea.Area3DStyle.Enable3D == true &&
|
||
!chartArea.chartAreaIsCurcular &&
|
||
chartArea.requireAxes &&
|
||
chartArea.matrix3D.IsInitialized())
|
||
{
|
||
// Get anotation Z coordinate (use scene depth or anchored point Z position)
|
||
float positionZ = chartArea.areaSceneDepth;
|
||
if(this.AnchorDataPoint != null && this.AnchorDataPoint.series != null)
|
||
{
|
||
float depth = 0f;
|
||
chartArea.GetSeriesZPositionAndDepth(
|
||
this.AnchorDataPoint.series,
|
||
out depth,
|
||
out positionZ);
|
||
positionZ += depth / 2f;
|
||
}
|
||
|
||
// Define 3D points of annotation object
|
||
Point3D[] annot3DPoints = new Point3D[3];
|
||
annot3DPoints[0] = new Point3D((float)relativeX, (float)relativeY, positionZ);
|
||
annot3DPoints[1] = new Point3D((float)(relativeX + relativeWidth), (float)(relativeY + relativeHeight), positionZ);
|
||
annot3DPoints[2] = new Point3D((float)anchorX, (float)anchorY, positionZ);
|
||
|
||
// Tranform cube coordinates
|
||
chartArea.matrix3D.TransformPoints( annot3DPoints );
|
||
|
||
// Get transformed coordinates
|
||
relativeX = annot3DPoints[0].X;
|
||
relativeY = annot3DPoints[0].Y;
|
||
anchorX = annot3DPoints[2].X;
|
||
anchorY = annot3DPoints[2].Y;
|
||
|
||
// Don't adjust size for text annotation
|
||
if (!(isTextAnnotation && this.IsSizeAlwaysRelative))
|
||
{
|
||
relativeWidth = annot3DPoints[1].X - relativeX;
|
||
relativeHeight = annot3DPoints[1].Y - relativeY;
|
||
}
|
||
}
|
||
|
||
//***********************************************************************
|
||
//** Provide "dummy" position at design time
|
||
//***********************************************************************
|
||
if(this.Chart != null && this.Chart.IsDesignMode())
|
||
{
|
||
if(double.IsNaN(relativeX))
|
||
{
|
||
relativeX = groupLocation.X;
|
||
saveCurrentPosition = false;
|
||
}
|
||
if(double.IsNaN(relativeY))
|
||
{
|
||
relativeY = groupLocation.Y;
|
||
saveCurrentPosition = false;
|
||
}
|
||
if(double.IsNaN(relativeWidth))
|
||
{
|
||
relativeWidth = 20.0 * groupScaleX;
|
||
saveCurrentPosition = false;
|
||
}
|
||
if(double.IsNaN(relativeHeight))
|
||
{
|
||
relativeHeight = 20.0 * groupScaleY;
|
||
saveCurrentPosition = false;
|
||
}
|
||
}
|
||
|
||
//***********************************************************************
|
||
//** Initialize returned values
|
||
//***********************************************************************
|
||
location = new PointF( (float)relativeX, (float)relativeY );
|
||
size = new SizeF( (float)relativeWidth, (float)relativeHeight );
|
||
anchorLocation = new PointF( (float)anchorX, (float)anchorY );
|
||
|
||
//***********************************************************************
|
||
//** Adjust text based annotaion position using SmartLabelStyle.
|
||
//***********************************************************************
|
||
// Check if smart labels are enabled
|
||
if (this.SmartLabelStyle.Enabled && isTextAnnotation &&
|
||
group == null)
|
||
{
|
||
// Anchor point must be set
|
||
if(!double.IsNaN(anchorX) && !double.IsNaN(anchorY) &&
|
||
double.IsNaN(this.X) && double.IsNaN(this.Y))
|
||
{
|
||
if(this.Chart != null &&
|
||
this.Chart.chartPicture != null)
|
||
{
|
||
// Remember old movement distance restriction
|
||
double oldMinMovingDistance = this.SmartLabelStyle.MinMovingDistance;
|
||
double oldMaxMovingDistance = this.SmartLabelStyle.MaxMovingDistance;
|
||
|
||
// Increase annotation moving restrictions according to the anchor offset
|
||
PointF anchorOffsetAbs = this.GetGraphics().GetAbsolutePoint(
|
||
new PointF((float)this.AnchorOffsetX, (float)this.AnchorOffsetY));
|
||
float maxAnchorOffsetAbs = Math.Max(anchorOffsetAbs.X, anchorOffsetAbs.Y);
|
||
if(maxAnchorOffsetAbs > 0.0)
|
||
{
|
||
this.SmartLabelStyle.MinMovingDistance += maxAnchorOffsetAbs;
|
||
this.SmartLabelStyle.MaxMovingDistance += maxAnchorOffsetAbs;
|
||
}
|
||
|
||
// Adjust label position using SmartLabelStyle algorithm
|
||
LabelAlignmentStyles labelAlignment = LabelAlignmentStyles.Bottom;
|
||
using (StringFormat format = new StringFormat())
|
||
{
|
||
SizeF markerSizeRel = new SizeF((float)this.AnchorOffsetX, (float)this.AnchorOffsetY);
|
||
PointF newlocation = this.Chart.chartPicture.annotationSmartLabel.AdjustSmartLabelPosition(
|
||
this.Common,
|
||
this.Chart.chartPicture.ChartGraph,
|
||
chartArea,
|
||
this.SmartLabelStyle,
|
||
location,
|
||
size,
|
||
format,
|
||
anchorLocation,
|
||
markerSizeRel,
|
||
labelAlignment,
|
||
(this is CalloutAnnotation));
|
||
|
||
// Restore old movement distance restriction
|
||
this.SmartLabelStyle.MinMovingDistance = oldMinMovingDistance;
|
||
this.SmartLabelStyle.MaxMovingDistance = oldMaxMovingDistance;
|
||
|
||
// Check if annotation should be hidden
|
||
if (newlocation.IsEmpty)
|
||
{
|
||
location = new PointF(float.NaN, float.NaN);
|
||
}
|
||
else
|
||
{
|
||
// Get new position using alignment in format
|
||
RectangleF newPosition = this.Chart.chartPicture.annotationSmartLabel.GetLabelPosition(
|
||
this.Chart.chartPicture.ChartGraph,
|
||
newlocation,
|
||
size,
|
||
format,
|
||
false);
|
||
|
||
// Set new location
|
||
location = newPosition.Location;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// Add annotation position into the list (to prevent overlapping)
|
||
using (StringFormat format = new StringFormat())
|
||
{
|
||
this.Chart.chartPicture.annotationSmartLabel.AddSmartLabelPosition(
|
||
this.Chart.chartPicture.ChartGraph,
|
||
location,
|
||
size,
|
||
format);
|
||
}
|
||
}
|
||
}
|
||
|
||
//***********************************************************************
|
||
//** Save calculated position
|
||
//***********************************************************************
|
||
if(saveCurrentPosition)
|
||
{
|
||
currentPositionRel = new RectangleF(location, size);
|
||
currentAnchorLocationRel = new PointF(anchorLocation.X, anchorLocation.Y);
|
||
}
|
||
}
|
||
|
||
#if Microsoft_CONTROL
|
||
/// <summary>
|
||
/// Set annotation object position using rectangle in relative coordinates.
|
||
/// Automatically converts relative coordinates to axes values if required.
|
||
/// </summary>
|
||
/// <param name="position">Position in relative coordinates.</param>
|
||
/// <param name="anchorPoint">Anchor location in relative coordinates.</param>
|
||
internal void SetPositionRelative(RectangleF position, PointF anchorPoint)
|
||
{
|
||
SetPositionRelative(position, anchorPoint, false);
|
||
}
|
||
#endif // Microsoft_CONTROL
|
||
|
||
/// <summary>
|
||
/// Set annotation object position using rectangle in relative coordinates.
|
||
/// Automatically converts relative coordinates to axes values if required.
|
||
/// </summary>
|
||
/// <param name="position">Position in relative coordinates.</param>
|
||
/// <param name="anchorPoint">Anchor location in relative coordinates.</param>
|
||
/// <param name="userInput">Indicates if position changing was a result of the user input.</param>
|
||
internal void SetPositionRelative(RectangleF position, PointF anchorPoint, bool userInput)
|
||
{
|
||
double newX = position.X;
|
||
double newY = position.Y;
|
||
double newRight = position.Right;
|
||
double newBottom = position.Bottom;
|
||
double newWidth = position.Width;
|
||
double newHeight = position.Height;
|
||
double newAnchorX = anchorPoint.X;
|
||
double newAnchorY = anchorPoint.Y;
|
||
|
||
//***********************************************************************
|
||
//** Set pre calculated position and anchor location
|
||
//***********************************************************************
|
||
this.currentPositionRel = new RectangleF(position.Location, position.Size);
|
||
this.currentAnchorLocationRel = new PointF(anchorPoint.X, anchorPoint.Y);
|
||
|
||
//***********************************************************************
|
||
//** Get vertical and horizontal axis
|
||
//***********************************************************************
|
||
Axis vertAxis = null;
|
||
Axis horizAxis = null;
|
||
GetAxes(ref vertAxis, ref horizAxis);
|
||
|
||
//***********************************************************************
|
||
//** Disable anchoring to point and axes in 3D
|
||
//** This is done due to the issues of moving elements in 3D space.
|
||
//***********************************************************************
|
||
ChartArea chartArea = null;
|
||
if(horizAxis != null && horizAxis.ChartArea != null)
|
||
{
|
||
chartArea = horizAxis.ChartArea;
|
||
}
|
||
if(vertAxis != null && vertAxis.ChartArea != null)
|
||
{
|
||
chartArea = vertAxis.ChartArea;
|
||
}
|
||
if(chartArea != null && chartArea.Area3DStyle.Enable3D == true)
|
||
{
|
||
// If anchor point was set - get its relative position and use it as an anchor point
|
||
if(this.AnchorDataPoint != null)
|
||
{
|
||
bool inRelativeCoordX = true;
|
||
bool inRelativeCoordY = true;
|
||
this.GetAnchorLocation(ref newAnchorX, ref newAnchorY, ref inRelativeCoordX, ref inRelativeCoordY);
|
||
this.currentAnchorLocationRel = new PointF((float)newAnchorX, (float)newAnchorY);
|
||
}
|
||
|
||
// In 3D always use relative annotation coordinates
|
||
// Disconnect annotation from axes and anchor point
|
||
this.AnchorDataPoint = null;
|
||
this.AxisX = null;
|
||
this.AxisY = null;
|
||
horizAxis = null;
|
||
vertAxis = null;
|
||
}
|
||
|
||
|
||
//***********************************************************************
|
||
//** Convert relative coordinates to axis values
|
||
//***********************************************************************
|
||
if(horizAxis != null)
|
||
{
|
||
newX = horizAxis.PositionToValue(newX, false);
|
||
if(!double.IsNaN(newAnchorX))
|
||
{
|
||
newAnchorX = horizAxis.PositionToValue(newAnchorX, false);
|
||
}
|
||
|
||
// Adjust for the IsLogarithmic axis
|
||
if( horizAxis.IsLogarithmic )
|
||
{
|
||
newX = Math.Pow( horizAxis.logarithmBase, newX );
|
||
if(!double.IsNaN(newAnchorX))
|
||
{
|
||
newAnchorX = Math.Pow( horizAxis.logarithmBase, newAnchorX );
|
||
}
|
||
}
|
||
|
||
if(!this.IsSizeAlwaysRelative)
|
||
{
|
||
if(float.IsNaN(position.Right) &&
|
||
!float.IsNaN(position.Width) &&
|
||
!float.IsNaN(anchorPoint.X) )
|
||
{
|
||
newRight = horizAxis.PositionToValue(anchorPoint.X + position.Width, false);
|
||
if( horizAxis.IsLogarithmic )
|
||
{
|
||
newRight = Math.Pow( horizAxis.logarithmBase, newRight );
|
||
}
|
||
newWidth = newRight - newAnchorX;
|
||
}
|
||
else
|
||
{
|
||
newRight = horizAxis.PositionToValue(position.Right, false);
|
||
if( horizAxis.IsLogarithmic )
|
||
{
|
||
newRight = Math.Pow( horizAxis.logarithmBase, newRight );
|
||
}
|
||
newWidth = newRight - newX;
|
||
}
|
||
}
|
||
}
|
||
if(vertAxis != null)
|
||
{
|
||
newY = vertAxis.PositionToValue(newY, false);
|
||
if(!double.IsNaN(newAnchorY))
|
||
{
|
||
newAnchorY = vertAxis.PositionToValue(newAnchorY, false);
|
||
}
|
||
|
||
// NOTE: Fixes issue #4113
|
||
// Adjust for the IsLogarithmic axis
|
||
if( vertAxis.IsLogarithmic )
|
||
{
|
||
newY = Math.Pow( vertAxis.logarithmBase, newY );
|
||
if(!double.IsNaN(newAnchorY))
|
||
{
|
||
newAnchorY = Math.Pow( vertAxis.logarithmBase, newAnchorY );
|
||
}
|
||
}
|
||
|
||
if(!this.IsSizeAlwaysRelative)
|
||
{
|
||
if(float.IsNaN(position.Bottom) &&
|
||
!float.IsNaN(position.Height) &&
|
||
!float.IsNaN(anchorPoint.Y) )
|
||
{
|
||
newBottom = vertAxis.PositionToValue(anchorPoint.Y + position.Height, false);
|
||
if( vertAxis.IsLogarithmic )
|
||
{
|
||
newBottom = Math.Pow( vertAxis.logarithmBase, newBottom );
|
||
}
|
||
newHeight = newBottom - newAnchorY;
|
||
}
|
||
else
|
||
{
|
||
newBottom = vertAxis.PositionToValue(position.Bottom, false);
|
||
if( vertAxis.IsLogarithmic )
|
||
{
|
||
newBottom = Math.Pow( vertAxis.logarithmBase, newBottom );
|
||
}
|
||
newHeight = newBottom - newY;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Fire position changing event when position changed by user.
|
||
if(userInput)
|
||
{
|
||
#if Microsoft_CONTROL
|
||
// Set flag that annotation position was changed
|
||
this.positionChanged = true;
|
||
|
||
// Fire position changing event
|
||
if(this.Chart != null)
|
||
{
|
||
AnnotationPositionChangingEventArgs args = new AnnotationPositionChangingEventArgs();
|
||
args.NewLocationX = newX;
|
||
args.NewLocationY = newY;
|
||
args.NewSizeWidth = newWidth;
|
||
args.NewSizeHeight = newHeight;
|
||
args.NewAnchorLocationX = newAnchorX;
|
||
args.NewAnchorLocationY = newAnchorY;
|
||
args.Annotation = this;
|
||
|
||
if(this.Chart.OnAnnotationPositionChanging(ref args))
|
||
{
|
||
// Get user changed position/anchor
|
||
newX = args.NewLocationX;
|
||
newY = args.NewLocationY;
|
||
newWidth = args.NewSizeWidth;
|
||
newHeight = args.NewSizeHeight;
|
||
newAnchorX = args.NewAnchorLocationX;
|
||
newAnchorY = args.NewAnchorLocationY;
|
||
}
|
||
}
|
||
#endif // Microsoft_CONTROL
|
||
}
|
||
|
||
// Adjust location & size
|
||
this.X = newX;
|
||
this.Y = newY;
|
||
this.Width = newWidth;
|
||
this.Height = newHeight;
|
||
this.AnchorX = newAnchorX;
|
||
this.AnchorY = newAnchorY;
|
||
|
||
// Invalidate annotation
|
||
this.Invalidate();
|
||
|
||
return;
|
||
}
|
||
/// <summary>
|
||
/// Adjust annotation location and\or size as a result of user action.
|
||
/// </summary>
|
||
/// <param name="movingDistance">Distance to resize/move the annotation.</param>
|
||
/// <param name="resizeMode">Resizing mode.</param>
|
||
virtual internal void AdjustLocationSize(SizeF movingDistance, ResizingMode resizeMode)
|
||
{
|
||
AdjustLocationSize(movingDistance, resizeMode, true);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Adjust annotation location and\or size as a result of user action.
|
||
/// </summary>
|
||
/// <param name="movingDistance">Distance to resize/move the annotation.</param>
|
||
/// <param name="resizeMode">Resizing mode.</param>
|
||
/// <param name="pixelCoord">Distance is in pixels, otherwise relative.</param>
|
||
virtual internal void AdjustLocationSize(SizeF movingDistance, ResizingMode resizeMode, bool pixelCoord)
|
||
{
|
||
AdjustLocationSize(movingDistance, resizeMode, pixelCoord, false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Adjust annotation location and\or size as a result of user action.
|
||
/// </summary>
|
||
/// <param name="movingDistance">Distance to resize/move the annotation.</param>
|
||
/// <param name="resizeMode">Resizing mode.</param>
|
||
/// <param name="pixelCoord">Distance is in pixels, otherwise relative.</param>
|
||
/// <param name="userInput">Indicates if position changing was a result of the user input.</param>
|
||
virtual internal void AdjustLocationSize(SizeF movingDistance, ResizingMode resizeMode, bool pixelCoord, bool userInput)
|
||
{
|
||
if(!movingDistance.IsEmpty)
|
||
{
|
||
// Convert pixel coordinates into relative
|
||
if(pixelCoord)
|
||
{
|
||
movingDistance = Chart.chartPicture.ChartGraph.GetRelativeSize(movingDistance);
|
||
}
|
||
|
||
// Get annotation position in relative coordinates
|
||
PointF firstPoint = PointF.Empty;
|
||
PointF anchorPoint = PointF.Empty;
|
||
SizeF size = SizeF.Empty;
|
||
if(userInput)
|
||
{
|
||
#if Microsoft_CONTROL
|
||
if(this.startMovePositionRel.X == 0f &&
|
||
this.startMovePositionRel.Y == 0f &&
|
||
this.startMovePositionRel.Width == 0f &&
|
||
this.startMovePositionRel.Height == 0f)
|
||
{
|
||
GetRelativePosition(out firstPoint, out size, out anchorPoint);
|
||
this.startMovePositionRel = new RectangleF(firstPoint, size);
|
||
this.startMoveAnchorLocationRel = new PointF(anchorPoint.X, anchorPoint.Y);
|
||
}
|
||
firstPoint = this.startMovePositionRel.Location;
|
||
size = this.startMovePositionRel.Size;
|
||
anchorPoint = this.startMoveAnchorLocationRel;
|
||
#else // Microsoft_CONTROL
|
||
GetRelativePosition(out firstPoint, out size, out anchorPoint);
|
||
#endif // Microsoft_CONTROL
|
||
|
||
}
|
||
else
|
||
{
|
||
GetRelativePosition(out firstPoint, out size, out anchorPoint);
|
||
}
|
||
|
||
if(resizeMode == ResizingMode.TopLeftHandle)
|
||
{
|
||
firstPoint.X -= movingDistance.Width;
|
||
firstPoint.Y -= movingDistance.Height;
|
||
size.Width += movingDistance.Width;
|
||
size.Height += movingDistance.Height;
|
||
}
|
||
else if(resizeMode == ResizingMode.TopHandle)
|
||
{
|
||
firstPoint.Y -= movingDistance.Height;
|
||
size.Height += movingDistance.Height;
|
||
}
|
||
else if(resizeMode == ResizingMode.TopRightHandle)
|
||
{
|
||
firstPoint.Y -= movingDistance.Height;
|
||
size.Width -= movingDistance.Width;
|
||
size.Height += movingDistance.Height;
|
||
}
|
||
else if(resizeMode == ResizingMode.RightHandle)
|
||
{
|
||
size.Width -= movingDistance.Width;
|
||
}
|
||
else if(resizeMode == ResizingMode.BottomRightHandle)
|
||
{
|
||
size.Width -= movingDistance.Width;
|
||
size.Height -= movingDistance.Height;
|
||
}
|
||
else if(resizeMode == ResizingMode.BottomHandle)
|
||
{
|
||
size.Height -= movingDistance.Height;
|
||
}
|
||
else if(resizeMode == ResizingMode.BottomLeftHandle)
|
||
{
|
||
firstPoint.X -= movingDistance.Width;
|
||
size.Width += movingDistance.Width;
|
||
size.Height -= movingDistance.Height;
|
||
}
|
||
else if(resizeMode == ResizingMode.LeftHandle)
|
||
{
|
||
firstPoint.X -= movingDistance.Width;
|
||
size.Width += movingDistance.Width;
|
||
}
|
||
else if(resizeMode == ResizingMode.AnchorHandle)
|
||
{
|
||
anchorPoint.X -= movingDistance.Width;
|
||
anchorPoint.Y -= movingDistance.Height;
|
||
}
|
||
else if(resizeMode == ResizingMode.Moving)
|
||
{
|
||
firstPoint.X -= movingDistance.Width;
|
||
firstPoint.Y -= movingDistance.Height;
|
||
}
|
||
|
||
// Make sure we do not override automatic Width and Heigth
|
||
if(resizeMode == ResizingMode.Moving)
|
||
{
|
||
if( double.IsNaN(this.Width) )
|
||
{
|
||
size.Width = float.NaN;
|
||
}
|
||
if( double.IsNaN(this.Height) )
|
||
{
|
||
size.Height = float.NaN;
|
||
}
|
||
}
|
||
|
||
// Make sure we do not override automatic X and Y
|
||
if(resizeMode == ResizingMode.AnchorHandle)
|
||
{
|
||
if( double.IsNaN(this.X) )
|
||
{
|
||
firstPoint.X = float.NaN;
|
||
}
|
||
if( double.IsNaN(this.Y) )
|
||
{
|
||
firstPoint.Y = float.NaN;
|
||
}
|
||
}
|
||
else if(double.IsNaN(this.AnchorX) || double.IsNaN(this.AnchorY) )
|
||
{
|
||
anchorPoint = new PointF(float.NaN, float.NaN);
|
||
}
|
||
|
||
// Set annotation position from rectangle in relative coordinates
|
||
SetPositionRelative(new RectangleF(firstPoint, size), anchorPoint, userInput);
|
||
}
|
||
return;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Anchor Point and Axes Converters
|
||
|
||
/// <summary>
|
||
/// Checks if annotation draw anything in the anchor position (except selection handle)
|
||
/// </summary>
|
||
/// <returns>True if annotation "connects" itself and anchor point visually.</returns>
|
||
virtual internal bool IsAnchorDrawn()
|
||
{
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets data point by name.
|
||
/// </summary>
|
||
/// <param name="dataPointName">Data point name to find.</param>
|
||
/// <returns>Data point.</returns>
|
||
internal DataPoint GetDataPointByName(string dataPointName)
|
||
{
|
||
DataPoint dataPoint = null;
|
||
|
||
if (Chart != null && dataPointName.Length > 0)
|
||
{
|
||
// Split series name and point index
|
||
int separatorIndex = dataPointName.IndexOf("\\r", StringComparison.Ordinal);
|
||
if (separatorIndex > 0)
|
||
{
|
||
string seriesName = dataPointName.Substring(0, separatorIndex);
|
||
string pointIndex = dataPointName.Substring(separatorIndex + 2);
|
||
|
||
int index;
|
||
if (int.TryParse(pointIndex, NumberStyles.Any, CultureInfo.InvariantCulture, out index))
|
||
{
|
||
dataPoint = Chart.Series[seriesName].Points[index];
|
||
}
|
||
}
|
||
}
|
||
|
||
return dataPoint;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets axis by name.
|
||
/// </summary>
|
||
/// <param name="axisName">Axis name to find.</param>
|
||
/// <returns>Data point.</returns>
|
||
private Axis GetAxisByName(string axisName)
|
||
{
|
||
Debug.Assert(axisName != null, "GetAxisByName: handed a null axis name");
|
||
|
||
Axis axis = null;
|
||
|
||
try
|
||
{
|
||
if (Chart != null && axisName.Length > 0)
|
||
{
|
||
// Split series name and point index
|
||
int separatorIndex = axisName.IndexOf("\\r", StringComparison.Ordinal);
|
||
if (separatorIndex > 0)
|
||
{
|
||
string areaName = axisName.Substring(0, separatorIndex);
|
||
string axisType = axisName.Substring(separatorIndex + 2);
|
||
switch ((AxisName)Enum.Parse(typeof(AxisName), axisType))
|
||
{
|
||
case (AxisName.X):
|
||
axis = Chart.ChartAreas[areaName].AxisX;
|
||
break;
|
||
case (AxisName.Y):
|
||
axis = Chart.ChartAreas[areaName].AxisY;
|
||
break;
|
||
case (AxisName.X2):
|
||
axis = Chart.ChartAreas[areaName].AxisX2;
|
||
break;
|
||
case (AxisName.Y2):
|
||
axis = Chart.ChartAreas[areaName].AxisY2;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
catch (ArgumentNullException)
|
||
{
|
||
axis = null;
|
||
}
|
||
catch (ArgumentException)
|
||
{
|
||
axis = null;
|
||
}
|
||
|
||
return axis;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets data point unique name.
|
||
/// </summary>
|
||
/// <param name="dataPoint">Data point to get the name for.</param>
|
||
/// <returns>Data point name.</returns>
|
||
internal string GetDataPointName(DataPoint dataPoint)
|
||
{
|
||
string name = String.Empty;
|
||
if(dataPoint.series != null)
|
||
{
|
||
int pointIndex = dataPoint.series.Points.IndexOf(dataPoint);
|
||
if(pointIndex >= 0)
|
||
{
|
||
name = dataPoint.series.Name +
|
||
"\\r" +
|
||
pointIndex.ToString(CultureInfo.InvariantCulture);
|
||
}
|
||
}
|
||
return name;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets axis unique name.
|
||
/// </summary>
|
||
/// <param name="axis">Axis to get the name for.</param>
|
||
/// <returns>Axis name.</returns>
|
||
private string GetAxisName(Axis axis)
|
||
{
|
||
string name = String.Empty;
|
||
if(axis.ChartArea != null)
|
||
{
|
||
name = axis.ChartArea.Name +
|
||
"\\r" +
|
||
axis.AxisName.ToString();
|
||
}
|
||
return name;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Z Order Methods
|
||
|
||
/// <summary>
|
||
/// Sends an annotation to the back of all annotations.
|
||
/// <seealso cref="BringToFront"/>
|
||
/// </summary>
|
||
virtual public void SendToBack()
|
||
{
|
||
// Find collection of annotation objects this annotation belongs too
|
||
AnnotationCollection collection = null;
|
||
if(Chart != null)
|
||
{
|
||
collection = Chart.Annotations;
|
||
}
|
||
|
||
// Check if annotation belongs to the group
|
||
AnnotationGroup group = AnnotationGroup;
|
||
if(group != null)
|
||
{
|
||
collection = group.Annotations;
|
||
}
|
||
|
||
// Check if annotation is found
|
||
if(collection != null)
|
||
{
|
||
Annotation annot = collection.FindByName(this.Name);
|
||
if(annot != null)
|
||
{
|
||
// Reinsert annotation at the beginning of the collection
|
||
collection.Remove(annot);
|
||
collection.Insert(0, annot);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Brings an annotation to the front of all annotations.
|
||
/// <seealso cref="SendToBack"/>
|
||
/// </summary>
|
||
virtual public void BringToFront()
|
||
{
|
||
// Find collection of annotation objects this annotation belongs too
|
||
AnnotationCollection collection = null;
|
||
if(Chart != null)
|
||
{
|
||
collection = Chart.Annotations;
|
||
}
|
||
|
||
// Check if annotation belongs to the group
|
||
AnnotationGroup group = AnnotationGroup;
|
||
if(group != null)
|
||
{
|
||
collection = group.Annotations;
|
||
}
|
||
|
||
// Check if annotation is found
|
||
if(collection != null)
|
||
{
|
||
Annotation annot = collection.FindByName(this.Name);
|
||
if(annot != null)
|
||
{
|
||
// Reinsert annotation at the end of the collection
|
||
collection.Remove(annot);
|
||
collection.Add(this);
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion // Z Order Methods
|
||
|
||
#region Group Related Methods
|
||
|
||
#endregion // Group Related Methods
|
||
|
||
#region SmartLabelStyle methods
|
||
|
||
/// <summary>
|
||
/// Adds anchor position to the list. Used to check SmartLabelStyle overlapping.
|
||
/// </summary>
|
||
/// <param name="list">List to add to.</param>
|
||
internal void AddSmartLabelMarkerPositions(ArrayList list)
|
||
{
|
||
// Anchor position is added to the list of non-overlapped markers
|
||
if(this.Visible && this.IsAnchorDrawn())
|
||
{
|
||
// Get vertical and horizontal axis
|
||
Axis vertAxis = null;
|
||
Axis horizAxis = null;
|
||
GetAxes(ref vertAxis, ref horizAxis);
|
||
|
||
// Get anchor position
|
||
double anchorX = double.NaN;
|
||
double anchorY = double.NaN;
|
||
bool relativeX = false;
|
||
bool relativeY = false;
|
||
this.GetAnchorLocation(ref anchorX, ref anchorY, ref relativeX, ref relativeY);
|
||
|
||
// Convert anchor location to relative coordinates
|
||
if(!double.IsNaN(anchorX) && !double.IsNaN(anchorY))
|
||
{
|
||
if( !relativeX && horizAxis != null )
|
||
{
|
||
anchorX = horizAxis.ValueToPosition(anchorX);
|
||
}
|
||
if( !relativeY && vertAxis != null )
|
||
{
|
||
anchorY = vertAxis.ValueToPosition(anchorY);
|
||
}
|
||
|
||
// Apply 3D transforamtion if required
|
||
ChartArea chartArea = null;
|
||
if(horizAxis != null && horizAxis.ChartArea != null)
|
||
{
|
||
chartArea = horizAxis.ChartArea;
|
||
}
|
||
if(vertAxis != null && vertAxis.ChartArea != null)
|
||
{
|
||
chartArea = vertAxis.ChartArea;
|
||
}
|
||
if(chartArea != null &&
|
||
chartArea.Area3DStyle.Enable3D == true &&
|
||
!chartArea.chartAreaIsCurcular &&
|
||
chartArea.requireAxes &&
|
||
chartArea.matrix3D.IsInitialized())
|
||
{
|
||
// Get anotation Z coordinate (use scene depth or anchored point Z position)
|
||
float positionZ = chartArea.areaSceneDepth;
|
||
if(this.AnchorDataPoint != null && this.AnchorDataPoint.series != null)
|
||
{
|
||
float depth = 0f;
|
||
chartArea.GetSeriesZPositionAndDepth(
|
||
this.AnchorDataPoint.series,
|
||
out depth,
|
||
out positionZ);
|
||
positionZ += depth / 2f;
|
||
}
|
||
|
||
// Define 3D points of annotation object
|
||
Point3D[] annot3DPoints = new Point3D[1];
|
||
annot3DPoints[0] = new Point3D((float)anchorX, (float)anchorY, positionZ);
|
||
|
||
// Tranform cube coordinates
|
||
chartArea.matrix3D.TransformPoints( annot3DPoints );
|
||
|
||
// Get transformed coordinates
|
||
anchorX = annot3DPoints[0].X;
|
||
anchorY = annot3DPoints[0].Y;
|
||
}
|
||
|
||
// Save selection handles position in array elements 0 and 4
|
||
if(this.GetGraphics() != null)
|
||
{
|
||
SizeF markerSizeRel = this.GetGraphics().GetRelativeSize(
|
||
new SizeF(1f, 1f));
|
||
RectangleF anchorRect = new RectangleF(
|
||
(float)anchorX - markerSizeRel.Width/2f,
|
||
(float)anchorY - markerSizeRel.Height/2f,
|
||
markerSizeRel.Width,
|
||
markerSizeRel.Height);
|
||
|
||
list.Add(anchorRect);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Public Anchoring Methods
|
||
|
||
/// <summary>
|
||
/// Anchors an annotation to a data point.
|
||
/// <seealso cref="AnchorDataPoint"/>
|
||
/// <seealso cref="AnchorX"/>
|
||
/// <seealso cref="AnchorY"/>
|
||
/// </summary>
|
||
/// <param name="dataPoint">
|
||
/// <see cref="DataPoint"/> to be anchored to.
|
||
/// </param>
|
||
/// <remarks>
|
||
/// Anchors an annotation to the specified data point.
|
||
/// </remarks>
|
||
public void SetAnchor(DataPoint dataPoint)
|
||
{
|
||
SetAnchor(dataPoint, null);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Anchors an annotation to two data points.
|
||
/// <seealso cref="AnchorDataPoint"/>
|
||
/// <seealso cref="AnchorX"/>
|
||
/// <seealso cref="AnchorY"/>
|
||
/// </summary>
|
||
/// <param name="dataPoint1">
|
||
/// First anchor <see cref="DataPoint"/>.
|
||
/// </param>
|
||
/// <param name="dataPoint2">
|
||
/// Second anchor <see cref="DataPoint"/>.
|
||
/// </param>
|
||
/// <remarks>
|
||
/// Anchors an annotation's top/left and bottom/right corners to the
|
||
/// specified data points.
|
||
/// </remarks>
|
||
public void SetAnchor(DataPoint dataPoint1, DataPoint dataPoint2)
|
||
{
|
||
// Set annotation position to automatic
|
||
this.X = double.NaN;
|
||
this.Y = double.NaN;
|
||
|
||
// Reset anchor point if any
|
||
this.AnchorX = double.NaN;
|
||
this.AnchorY = double.NaN;
|
||
|
||
// Set anchor point
|
||
this.AnchorDataPoint = dataPoint1;
|
||
|
||
// Get vertical and horizontal axis
|
||
Axis vertAxis = null;
|
||
Axis horizAxis = null;
|
||
GetAxes(ref vertAxis, ref horizAxis);
|
||
|
||
// Set Width and Height in axis coordinates
|
||
if(dataPoint2 != null && dataPoint1 != null)
|
||
{
|
||
this._anchorDataPoint2 = dataPoint2;
|
||
}
|
||
|
||
// Invalidate annotation
|
||
this.Invalidate();
|
||
}
|
||
|
||
#endregion // Public Anchoring Methods
|
||
|
||
#region Placement Methods
|
||
|
||
#if Microsoft_CONTROL
|
||
|
||
/// <summary>
|
||
/// Begins end user placement of an annotation using the mouse.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// When this method is called, the end user is allowed to place an annotation using the
|
||
/// mouse.
|
||
/// <para>
|
||
/// Placement will finish when the end user specifies all required points, or
|
||
/// the <see cref="EndPlacement"/> method is called.</para>
|
||
/// </remarks>
|
||
virtual public void BeginPlacement()
|
||
{
|
||
// Can't place annotations inside the group
|
||
if(this.AnnotationGroup != null)
|
||
{
|
||
throw (new InvalidOperationException(SR.ExceptionAnnotationGroupedUnableToStartPlacement));
|
||
}
|
||
|
||
if(this.Chart != null)
|
||
{
|
||
// Set the annotation object which is currently placed
|
||
this.Chart.Annotations.placingAnnotation = this;
|
||
}
|
||
else
|
||
{
|
||
throw (new InvalidOperationException(SR.ExceptionAnnotationNotInCollection));
|
||
}
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// Ends user placement of an annotation.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Ends an annotation placement operation previously started by a
|
||
/// <see cref="BeginPlacement"/> method call.
|
||
/// <para>
|
||
/// Calling this method is not required, since placement will automatically
|
||
/// end when an end user enters all required points. However, it is useful when an annotation
|
||
/// placement operation needs to be aborted for some reason.
|
||
/// </para>
|
||
/// </remarks>
|
||
virtual public void EndPlacement()
|
||
{
|
||
if(this.Chart != null)
|
||
{
|
||
// Reset currently placed annotation object
|
||
this.Chart.Annotations.placingAnnotation = null;
|
||
|
||
// Restore default cursor
|
||
this.Chart.Cursor = this.Chart.defaultCursor;
|
||
|
||
// Clear last placement mouse position
|
||
this.lastPlacementPosition = PointF.Empty;
|
||
|
||
// Fire annotation placed event
|
||
this.Chart.OnAnnotationPlaced(this);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handles mouse down event during annotation placement.
|
||
/// </summary>
|
||
/// <param name="point">Mouse cursor position in pixels.</param>
|
||
/// <param name="buttons">Mouse button down.</param>
|
||
internal virtual void PlacementMouseDown(PointF point, MouseButtons buttons)
|
||
{
|
||
if(buttons == MouseButtons.Right)
|
||
{
|
||
// Stop any pacement
|
||
this.EndPlacement();
|
||
}
|
||
if(buttons == MouseButtons.Left &&
|
||
IsValidPlacementPosition(point.X, point.Y))
|
||
{
|
||
if(this.lastPlacementPosition.IsEmpty)
|
||
{
|
||
// Remeber position where mouse was clicked
|
||
this.lastPlacementPosition = this.GetGraphics().GetRelativePoint(point);
|
||
|
||
// Get annotation position in relative coordinates
|
||
PointF firstPoint = PointF.Empty;
|
||
PointF anchorPoint = PointF.Empty;
|
||
SizeF size = SizeF.Empty;
|
||
this.GetRelativePosition(out firstPoint, out size, out anchorPoint);
|
||
|
||
// Set annotation X, Y coordinate
|
||
if(this.AllowMoving)
|
||
{
|
||
firstPoint = this.GetGraphics().GetRelativePoint(point);
|
||
|
||
// Do not change default position
|
||
if(double.IsNaN(this.AnchorX))
|
||
{
|
||
anchorPoint.X = float.NaN;
|
||
}
|
||
if(double.IsNaN(this.AnchorY))
|
||
{
|
||
anchorPoint.Y = float.NaN;
|
||
}
|
||
|
||
}
|
||
else if(this.AllowAnchorMoving)
|
||
{
|
||
anchorPoint = this.GetGraphics().GetRelativePoint(point);
|
||
|
||
// Do not change default position
|
||
if(double.IsNaN(this.X))
|
||
{
|
||
firstPoint.X = float.NaN;
|
||
}
|
||
if(double.IsNaN(this.Y))
|
||
{
|
||
firstPoint.Y = float.NaN;
|
||
}
|
||
}
|
||
|
||
// Do not change default size
|
||
if(double.IsNaN(this.Width))
|
||
{
|
||
size.Width = float.NaN;
|
||
}
|
||
if(double.IsNaN(this.Height))
|
||
{
|
||
size.Height = float.NaN;
|
||
}
|
||
|
||
// Set annotation position
|
||
this.positionChanged = true;
|
||
this.SetPositionRelative(
|
||
new RectangleF(firstPoint, size),
|
||
anchorPoint,
|
||
true);
|
||
|
||
// Invalidate and update the chart
|
||
if(Chart != null)
|
||
{
|
||
Invalidate();
|
||
Chart.UpdateAnnotations();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handles mouse up event during annotation placement.
|
||
/// </summary>
|
||
/// <param name="point">Mouse cursor position in pixels.</param>
|
||
/// <param name="buttons">Mouse button Up.</param>
|
||
/// <returns>Return true when placing finished.</returns>
|
||
internal virtual bool PlacementMouseUp(PointF point, MouseButtons buttons)
|
||
{
|
||
bool result = false;
|
||
if(buttons == MouseButtons.Left)
|
||
{
|
||
// Get annotation position in relative coordinates
|
||
PointF firstPoint = PointF.Empty;
|
||
PointF anchorPoint = PointF.Empty;
|
||
SizeF size = SizeF.Empty;
|
||
this.GetRelativePosition(out firstPoint, out size, out anchorPoint);
|
||
|
||
if(this.AllowResizing)
|
||
{
|
||
PointF pointRel = this.GetGraphics().GetRelativePoint(point);
|
||
size = new SizeF(
|
||
pointRel.X - this.lastPlacementPosition.X,
|
||
pointRel.Y - this.lastPlacementPosition.Y);
|
||
}
|
||
else
|
||
{
|
||
// Do not change default size
|
||
if(double.IsNaN(this.Width))
|
||
{
|
||
size.Width = float.NaN;
|
||
}
|
||
if(double.IsNaN(this.Height))
|
||
{
|
||
size.Height = float.NaN;
|
||
}
|
||
}
|
||
|
||
// Do not change default position
|
||
if(double.IsNaN(this.X))
|
||
{
|
||
firstPoint.X = float.NaN;
|
||
}
|
||
if(double.IsNaN(this.Y))
|
||
{
|
||
firstPoint.Y = float.NaN;
|
||
}
|
||
if(double.IsNaN(this.AnchorX))
|
||
{
|
||
anchorPoint.X = float.NaN;
|
||
}
|
||
if(double.IsNaN(this.AnchorY))
|
||
{
|
||
anchorPoint.Y = float.NaN;
|
||
}
|
||
|
||
// Set annotation position
|
||
this.positionChanged = true;
|
||
this.SetPositionRelative(
|
||
new RectangleF(firstPoint, size),
|
||
anchorPoint,
|
||
true);
|
||
|
||
// End placement
|
||
if(!size.IsEmpty || !this.AllowResizing)
|
||
{
|
||
result = true;
|
||
this.EndPlacement();
|
||
}
|
||
|
||
// Invalidate and update the chart
|
||
if(Chart != null)
|
||
{
|
||
Invalidate();
|
||
Chart.UpdateAnnotations();
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handles mouse move event during annotation placement.
|
||
/// </summary>
|
||
/// <param name="point">Mouse cursor position in pixels.</param>
|
||
internal virtual void PlacementMouseMove(PointF point)
|
||
{
|
||
// Check if annotation was moved
|
||
if( this.GetGraphics() != null &&
|
||
!this.lastPlacementPosition.IsEmpty)
|
||
{
|
||
// Get annotation position in relative coordinates
|
||
PointF firstPoint = PointF.Empty;
|
||
PointF anchorPoint = PointF.Empty;
|
||
SizeF size = SizeF.Empty;
|
||
this.GetRelativePosition(out firstPoint, out size, out anchorPoint);
|
||
|
||
if(this.AllowResizing)
|
||
{
|
||
PointF pointRel = this.GetGraphics().GetRelativePoint(point);
|
||
size = new SizeF(
|
||
pointRel.X - this.lastPlacementPosition.X,
|
||
pointRel.Y - this.lastPlacementPosition.Y);
|
||
}
|
||
|
||
// Do not change default position
|
||
if(double.IsNaN(this.X))
|
||
{
|
||
firstPoint.X = float.NaN;
|
||
}
|
||
if(double.IsNaN(this.Y))
|
||
{
|
||
firstPoint.Y = float.NaN;
|
||
}
|
||
if(double.IsNaN(this.AnchorX))
|
||
{
|
||
anchorPoint.X = float.NaN;
|
||
}
|
||
if(double.IsNaN(this.AnchorY))
|
||
{
|
||
anchorPoint.Y = float.NaN;
|
||
}
|
||
|
||
// Set annotation position
|
||
this.positionChanged = true;
|
||
this.SetPositionRelative(
|
||
new RectangleF(firstPoint, size),
|
||
anchorPoint,
|
||
true);
|
||
|
||
// Invalidate and update the chart
|
||
if(this.Chart != null)
|
||
{
|
||
Invalidate();
|
||
this.Chart.UpdateAnnotations();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Checks if specified position is valid for placement.
|
||
/// </summary>
|
||
/// <param name="x">X coordinate.</param>
|
||
/// <param name="y">Y coordinate.</param>
|
||
/// <returns>True if annotation can be placed at specified coordinates.</returns>
|
||
virtual internal bool IsValidPlacementPosition(float x, float y)
|
||
{
|
||
if(this.Chart != null &&
|
||
this.GetGraphics() != null)
|
||
{
|
||
// Check if cursor is over the area where placement allowed
|
||
// If so - change cursor to cross
|
||
RectangleF placementRect = new RectangleF(0f, 0f, 100f, 100f);
|
||
if(this.ClipToChartArea.Length > 0 &&
|
||
this.ClipToChartArea != Constants.NotSetValue)
|
||
{
|
||
ChartArea area = Chart.ChartAreas[this.ClipToChartArea];
|
||
placementRect = area.PlotAreaPosition.ToRectangleF();
|
||
}
|
||
placementRect = this.GetGraphics().GetAbsoluteRectangle(placementRect);
|
||
if(placementRect.Contains(x, y))
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
#endif // Microsoft_CONTROL
|
||
|
||
#endregion // Placement Methods
|
||
|
||
#region Helper Methods
|
||
|
||
/// <summary>
|
||
/// Helper method that checks if annotation is visible.
|
||
/// </summary>
|
||
/// <returns>True if annotation is visible.</returns>
|
||
internal bool IsVisible()
|
||
{
|
||
if(this.Visible)
|
||
{
|
||
if(this.Chart != null)
|
||
{
|
||
// Check if annotation is anchored to the data point
|
||
ChartArea area = null;
|
||
if(this.AnchorDataPoint != null &&
|
||
this.AnchorDataPoint.series != null)
|
||
{
|
||
if(this.Chart.ChartAreas.IndexOf(this.AnchorDataPoint.series.ChartArea) >= 0)
|
||
{
|
||
area = this.Chart.ChartAreas[this.AnchorDataPoint.series.ChartArea];
|
||
}
|
||
}
|
||
if(area == null &&
|
||
this._anchorDataPoint2 != null &&
|
||
this._anchorDataPoint2.series != null)
|
||
{
|
||
if(this.Chart.ChartAreas.IndexOf(this._anchorDataPoint2.series.ChartArea) >= 0)
|
||
{
|
||
area = this.Chart.ChartAreas[this._anchorDataPoint2.series.ChartArea];
|
||
}
|
||
}
|
||
|
||
// Check if annotation uses chart area axis values
|
||
if(area == null && this.AxisX != null)
|
||
{
|
||
area = this.AxisX.ChartArea;
|
||
}
|
||
if(area == null && this.AxisY != null)
|
||
{
|
||
area = this.AxisY.ChartArea;
|
||
}
|
||
|
||
// Check if associated area is visible
|
||
if(area != null &&
|
||
!area.Visible)
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Resets pre-calculated annotation position.
|
||
/// </summary>
|
||
internal void ResetCurrentRelativePosition()
|
||
{
|
||
this.currentPositionRel = new RectangleF(float.NaN, float.NaN, float.NaN, float.NaN);
|
||
this.currentAnchorLocationRel = new PointF(float.NaN, float.NaN);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Replaces predefined keyword inside the string with their values if
|
||
/// annotation is anchored to the data point.
|
||
/// </summary>
|
||
/// <param name="strOriginal">Original string with keywords.</param>
|
||
/// <returns>Modified string.</returns>
|
||
internal string ReplaceKeywords(string strOriginal)
|
||
{
|
||
if(this.AnchorDataPoint != null)
|
||
{
|
||
return this.AnchorDataPoint.ReplaceKeywords(strOriginal);
|
||
}
|
||
return strOriginal;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Checks if anchor point of the annotation is visible.
|
||
/// </summary>
|
||
/// <returns>True if anchor point is visible.</returns>
|
||
internal bool IsAnchorVisible()
|
||
{
|
||
// Get axes objects
|
||
Axis vertAxis = null;
|
||
Axis horizAxis = null;
|
||
GetAxes(ref vertAxis, ref horizAxis);
|
||
|
||
// Get anchor position
|
||
bool inRelativeAnchorX = false;
|
||
bool inRelativeAnchorY = false;
|
||
double anchorX = this.AnchorX;
|
||
double anchorY = this.AnchorY;
|
||
GetAnchorLocation(ref anchorX, ref anchorY, ref inRelativeAnchorX, ref inRelativeAnchorY);
|
||
|
||
// Check if anchor is set
|
||
if( !double.IsNaN(anchorX) && !double.IsNaN(anchorY) )
|
||
{
|
||
// Check if anchor is in axes coordinates
|
||
if(this.AnchorDataPoint != null ||
|
||
this.AxisX != null ||
|
||
this.AxisY != null)
|
||
{
|
||
// Convert anchor point to relative coordinates
|
||
if(!inRelativeAnchorX && horizAxis != null)
|
||
{
|
||
anchorX = horizAxis.ValueToPosition(anchorX);
|
||
}
|
||
if(!inRelativeAnchorY && vertAxis != null)
|
||
{
|
||
anchorY = vertAxis.ValueToPosition(anchorY);
|
||
}
|
||
|
||
// Get chart area
|
||
ChartArea chartArea = null;
|
||
if(horizAxis != null)
|
||
{
|
||
chartArea = horizAxis.ChartArea;
|
||
}
|
||
if(chartArea == null && vertAxis != null)
|
||
{
|
||
chartArea = vertAxis.ChartArea;
|
||
}
|
||
|
||
// Apply 3D transforamtion if required
|
||
if(chartArea != null && chartArea.Area3DStyle.Enable3D == true)
|
||
{
|
||
if(!chartArea.chartAreaIsCurcular &&
|
||
chartArea.requireAxes &&
|
||
chartArea.matrix3D.IsInitialized())
|
||
{
|
||
// Get anotation Z coordinate (use scene depth or anchored point Z position)
|
||
float positionZ = chartArea.areaSceneDepth;
|
||
if (this.AnchorDataPoint != null && this.AnchorDataPoint.series != null)
|
||
{
|
||
float depth = 0f;
|
||
chartArea.GetSeriesZPositionAndDepth(
|
||
this.AnchorDataPoint.series,
|
||
out depth,
|
||
out positionZ);
|
||
positionZ += depth / 2f;
|
||
}
|
||
|
||
// Define 3D points of annotation object
|
||
Point3D[] annot3DPoints = new Point3D[1];
|
||
annot3DPoints[0] = new Point3D((float)anchorX, (float)anchorY, positionZ);
|
||
|
||
// Tranform cube coordinates
|
||
chartArea.matrix3D.TransformPoints(annot3DPoints);
|
||
|
||
// Get transformed coordinates
|
||
anchorX = annot3DPoints[0].X;
|
||
anchorY = annot3DPoints[0].Y;
|
||
}
|
||
}
|
||
|
||
// Get plot rectangle position and inflate it slightly
|
||
// to solve any float rounding issues.
|
||
RectangleF rect = chartArea.PlotAreaPosition.ToRectangleF();
|
||
rect.Inflate(0.00001f, 0.00001f);
|
||
|
||
// Check if anchor point is in the plotting area
|
||
if(!rect.Contains((float)anchorX, (float)anchorY))
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Returns chart graphics objects.
|
||
/// </summary>
|
||
/// <returns>Chart graphics object.</returns>
|
||
internal ChartGraphics GetGraphics()
|
||
{
|
||
if (this.Common != null)
|
||
{
|
||
return this.Common.graph;
|
||
}
|
||
return null;
|
||
}
|
||
#if Microsoft_CONTROL
|
||
/// <summary>
|
||
/// Checks if provided pixel coordinate is contained in one of the
|
||
/// selection handles rectangle.
|
||
/// </summary>
|
||
/// <param name="point">Coordinate in pixels.</param>
|
||
/// <returns>Resizing mode.</returns>
|
||
internal ResizingMode GetSelectionHandle(PointF point)
|
||
{
|
||
ResizingMode resizingMode = ResizingMode.None;
|
||
|
||
if( this.Common != null &&
|
||
this.Common.graph != null)
|
||
{
|
||
// Convert point to relative coordinates
|
||
point = this.Common.graph.GetRelativePoint(point);
|
||
|
||
// Check if point is in one of the selection handles
|
||
if(this.selectionRects != null)
|
||
{
|
||
for(int index = 0; index < this.selectionRects.Length; index++)
|
||
{
|
||
if(!this.selectionRects[index].IsEmpty &&
|
||
this.selectionRects[index].Contains(point))
|
||
{
|
||
if(index > (int)ResizingMode.AnchorHandle)
|
||
{
|
||
resizingMode = ResizingMode.MovingPathPoints;
|
||
this.currentPathPointIndex = index - 9;
|
||
}
|
||
else
|
||
{
|
||
resizingMode = (ResizingMode)index;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return resizingMode;
|
||
}
|
||
#endif //Microsoft_CONTROL
|
||
/// <summary>
|
||
/// Gets data point X or Y axis.
|
||
/// </summary>
|
||
/// <param name="dataPoint">Data point to get the axis for.</param>
|
||
/// <param name="axisName">X or Y axis to get.</param>
|
||
/// <returns>Data point axis.</returns>
|
||
private Axis GetDataPointAxis(DataPoint dataPoint, AxisName axisName)
|
||
{
|
||
if (dataPoint != null && dataPoint.series != null && Chart != null)
|
||
{
|
||
// Get data point chart area
|
||
ChartArea chartArea = Chart.ChartAreas[dataPoint.series.ChartArea];
|
||
|
||
// Get point X axis
|
||
if ((axisName == AxisName.X || axisName == AxisName.X2) &&
|
||
!chartArea.switchValueAxes)
|
||
{
|
||
return chartArea.GetAxis(axisName, dataPoint.series.XAxisType, dataPoint.series.XSubAxisName);
|
||
}
|
||
else
|
||
{
|
||
return chartArea.GetAxis(axisName, dataPoint.series.YAxisType, dataPoint.series.YSubAxisName);
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets annotation vertical and horizontal axes.
|
||
/// </summary>
|
||
/// <param name="vertAxis">Returns annotation vertical axis or null.</param>
|
||
/// <param name="horizAxis">Returns annotation horizontal axis or null.</param>
|
||
internal void GetAxes(ref Axis vertAxis, ref Axis horizAxis)
|
||
{
|
||
vertAxis = null;
|
||
horizAxis = null;
|
||
|
||
if(this.AxisX != null && this.AxisX.ChartArea != null)
|
||
{
|
||
if(this.AxisX.ChartArea.switchValueAxes)
|
||
{
|
||
vertAxis = this.AxisX;
|
||
}
|
||
else
|
||
{
|
||
horizAxis = this.AxisX;
|
||
}
|
||
}
|
||
if(this.AxisY != null && this.AxisY.ChartArea != null)
|
||
{
|
||
if(this.AxisY.ChartArea.switchValueAxes)
|
||
{
|
||
horizAxis = this.AxisY;
|
||
}
|
||
else
|
||
{
|
||
vertAxis = this.AxisY;
|
||
}
|
||
}
|
||
|
||
// Get axes from attached data point
|
||
if(this.AnchorDataPoint != null)
|
||
{
|
||
if(horizAxis == null)
|
||
{
|
||
horizAxis = GetDataPointAxis(this.AnchorDataPoint, AxisName.X);
|
||
|
||
// For chart types like Bar, RangeBar and others, position of X and Y axes are flipped
|
||
if (horizAxis != null && horizAxis.ChartArea != null && horizAxis.ChartArea.switchValueAxes)
|
||
{
|
||
horizAxis = GetDataPointAxis(this.AnchorDataPoint, AxisName.Y);
|
||
}
|
||
}
|
||
if(vertAxis == null)
|
||
{
|
||
vertAxis = GetDataPointAxis(this.AnchorDataPoint, AxisName.Y);
|
||
|
||
// For chart types like Bar, RangeBar and others, position of X and Y axes are flipped
|
||
if (vertAxis != null && vertAxis.ChartArea != null && vertAxis.ChartArea.switchValueAxes)
|
||
{
|
||
vertAxis = GetDataPointAxis(this.AnchorDataPoint, AxisName.X);
|
||
}
|
||
}
|
||
}
|
||
|
||
// No axes coordinate system for grouped annotations
|
||
if(vertAxis != null || horizAxis != null)
|
||
{
|
||
if(this.AnnotationGroup != null)
|
||
{
|
||
throw (new InvalidOperationException(SR.ExceptionAnnotationGroupedAxisMustBeEmpty));
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#endregion
|
||
|
||
#region IDisposable Members
|
||
|
||
/// <summary>
|
||
/// Releases unmanaged and - optionally - managed resources
|
||
/// </summary>
|
||
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
|
||
protected override void Dispose(bool disposing)
|
||
{
|
||
if (disposing)
|
||
{
|
||
//Free managed resources
|
||
if (_fontCache != null)
|
||
{
|
||
_fontCache.Dispose();
|
||
_fontCache = null;
|
||
}
|
||
}
|
||
base.Dispose(disposing);
|
||
}
|
||
|
||
|
||
#endregion
|
||
}
|
||
|
||
#if Microsoft_CONTROL
|
||
|
||
/// <summary>
|
||
/// This class is used to stores position changing event data for an annotation.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Provides additional data like the new annotation and anchor position when an end user
|
||
/// is moving the annotation with the mouse.
|
||
/// <para>
|
||
/// Can be used to restrict annotation movement, or snap the annotation position to
|
||
/// specific points.
|
||
/// </para>
|
||
/// </remarks>
|
||
[
|
||
SRDescription("DescriptionAttributeAnnotationPositionChangingEventArgs_AnnotationPositionChangingEventArgs"),
|
||
]
|
||
public class AnnotationPositionChangingEventArgs : EventArgs
|
||
{
|
||
#region Fields
|
||
|
||
private Annotation _Annotation = null;
|
||
/// <summary>
|
||
/// Gets or sets the annotation the event is fired for.
|
||
/// </summary>
|
||
public Annotation Annotation
|
||
{
|
||
get { return _Annotation; }
|
||
set { _Annotation = value; }
|
||
}
|
||
|
||
private double _NewLocationX = 0.0;
|
||
/// <summary>
|
||
/// Gets or sets the new X location of the annotation.
|
||
/// </summary>
|
||
public double NewLocationX
|
||
{
|
||
get { return _NewLocationX; }
|
||
set { _NewLocationX = value; }
|
||
}
|
||
|
||
private double _NewLocationY = 0.0;
|
||
/// <summary>
|
||
/// Gets or sets the new Y location of the annotation.
|
||
/// </summary>
|
||
public double NewLocationY
|
||
{
|
||
get { return _NewLocationY; }
|
||
set { _NewLocationY = value; }
|
||
}
|
||
|
||
private double _NewSizeWidth = 0.0;
|
||
/// <summary>
|
||
/// Gets or sets the new width of the annotation.
|
||
/// </summary>
|
||
public double NewSizeWidth
|
||
{
|
||
get { return _NewSizeWidth; }
|
||
set { _NewSizeWidth = value; }
|
||
}
|
||
|
||
private double _NewSizeHeight = 0.0;
|
||
/// <summary>
|
||
/// Gets or sets the new height of the annotation.
|
||
/// </summary>
|
||
public double NewSizeHeight
|
||
{
|
||
get { return _NewSizeHeight; }
|
||
set { _NewSizeHeight = value; }
|
||
}
|
||
|
||
private double _NewAnchorLocationX = 0.0;
|
||
/// <summary>
|
||
/// Gets or sets the new annotation anchor point X location.
|
||
/// </summary>
|
||
public double NewAnchorLocationX
|
||
{
|
||
get { return _NewAnchorLocationX; }
|
||
set { _NewAnchorLocationX = value; }
|
||
}
|
||
|
||
private double _NewAnchorLocationY = 0.0;
|
||
/// <summary>
|
||
/// Gets or sets the new annotation anchor point Y location.
|
||
/// </summary>
|
||
public double NewAnchorLocationY
|
||
{
|
||
get { return _NewAnchorLocationY; }
|
||
set { _NewAnchorLocationY = value; }
|
||
}
|
||
|
||
#endregion // Fields
|
||
|
||
#region Properties
|
||
|
||
|
||
/// <summary>
|
||
/// Gets or sets the new location and size of the annotation.
|
||
/// </summary>
|
||
[
|
||
Browsable(false),
|
||
EditorBrowsableAttribute(EditorBrowsableState.Never),
|
||
]
|
||
public RectangleF NewPosition
|
||
{
|
||
get
|
||
{
|
||
return new RectangleF(
|
||
(float)this.NewLocationX,
|
||
(float)this.NewLocationY,
|
||
(float)this.NewSizeWidth,
|
||
(float)this.NewSizeHeight);
|
||
}
|
||
set
|
||
{
|
||
this.NewLocationX = value.X;
|
||
this.NewLocationY = value.Y;
|
||
this.NewSizeWidth = value.Width;
|
||
this.NewSizeHeight = value.Height;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the new anchor location of the annotation.
|
||
/// </summary>
|
||
[
|
||
Browsable(false),
|
||
EditorBrowsableAttribute(EditorBrowsableState.Never),
|
||
]
|
||
public PointF NewAnchorLocation
|
||
{
|
||
get
|
||
{
|
||
return new PointF(
|
||
(float)this.NewAnchorLocationX,
|
||
(float)this.NewAnchorLocationY);
|
||
}
|
||
set
|
||
{
|
||
this.NewAnchorLocationX = value.X;
|
||
this.NewAnchorLocationY = value.Y;
|
||
}
|
||
}
|
||
|
||
#endregion // Properties
|
||
}
|
||
|
||
#endif //Microsoft_CONTROL
|
||
}
|