536cd135cc
Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
845 lines
26 KiB
C#
845 lines
26 KiB
C#
//-------------------------------------------------------------
|
||
// <copyright company=’Microsoft Corporation’>
|
||
// Copyright © Microsoft Corporation. All Rights Reserved.
|
||
// </copyright>
|
||
//-------------------------------------------------------------
|
||
// @owner=alexgor, deliant
|
||
//=================================================================
|
||
// File: AnnotationCollection.cs
|
||
//
|
||
// Namespace: System.Web.UI.WebControls[Windows.Forms].Charting
|
||
//
|
||
// Classes: AnnotationCollection, AnnotationCollectionEditor
|
||
//
|
||
// Purpose: Collection of annotation objects.
|
||
//
|
||
// Reviewed:
|
||
//
|
||
//===================================================================
|
||
|
||
#region Used namespace
|
||
using System;
|
||
using System.Collections;
|
||
using System.Collections.Specialized;
|
||
using System.ComponentModel;
|
||
using System.ComponentModel.Design;
|
||
using System.Data;
|
||
using System.Drawing;
|
||
using System.Drawing.Design;
|
||
using System.Drawing.Text;
|
||
using System.Drawing.Drawing2D;
|
||
using System.Globalization;
|
||
using System.Diagnostics.CodeAnalysis;
|
||
|
||
#if Microsoft_CONTROL
|
||
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
|
||
{
|
||
/// <summary>
|
||
/// <b>AnnotationCollection</b> is a collection that stores chart annotation objects.
|
||
/// <seealso cref="Charting.Chart.Annotations"/>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// All chart annotations are stored in this collection. It is exposed as
|
||
/// a <see cref="Charting.Chart.Annotations"/> property of the chart. It is also used to
|
||
/// store annotations inside the <see cref="AnnotationGroup"/> class.
|
||
/// <para>
|
||
/// This class includes methods for adding, inserting, iterating and removing annotations.
|
||
/// </para>
|
||
/// </remarks>
|
||
[
|
||
SRDescription("DescriptionAttributeAnnotations3"),
|
||
]
|
||
#if ASPPERM_35
|
||
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
|
||
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
|
||
#endif
|
||
public class AnnotationCollection : ChartNamedElementCollection<Annotation>
|
||
{
|
||
#region Fields
|
||
|
||
/// <summary>
|
||
/// Group this collection belongs too
|
||
/// </summary>
|
||
internal AnnotationGroup AnnotationGroup { get; set; }
|
||
|
||
#if Microsoft_CONTROL
|
||
|
||
// Annotation object that was last clicked on
|
||
internal Annotation lastClickedAnnotation = null;
|
||
|
||
// Start point of annotation moving or resizing
|
||
private PointF _movingResizingStartPoint = PointF.Empty;
|
||
|
||
// Current resizing mode
|
||
private ResizingMode _resizingMode = ResizingMode.None;
|
||
|
||
// Annotation object which is currently placed on the chart
|
||
internal Annotation placingAnnotation = null;
|
||
|
||
#endif
|
||
|
||
#endregion
|
||
|
||
#region Construction and Initialization
|
||
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="AnnotationCollection"/> class.
|
||
/// </summary>
|
||
/// <param name="parent">The parent chart element.</param>
|
||
internal AnnotationCollection(IChartElement parent) : base(parent)
|
||
{
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Items Inserting and Removing Notification methods
|
||
|
||
/// <summary>
|
||
/// Initializes the specified item.
|
||
/// </summary>
|
||
/// <param name="item">The item.</param>
|
||
internal override void Initialize(Annotation item)
|
||
{
|
||
if (item != null)
|
||
{
|
||
TextAnnotation textAnnotation = item as TextAnnotation;
|
||
if (textAnnotation != null && string.IsNullOrEmpty(textAnnotation.Text) && Chart != null && Chart.IsDesignMode())
|
||
{
|
||
textAnnotation.Text = item.Name;
|
||
}
|
||
|
||
//If the collection belongs to annotation group we need to pass a ref to this group to all the child annotations
|
||
if (this.AnnotationGroup != null)
|
||
{
|
||
item.annotationGroup = this.AnnotationGroup;
|
||
}
|
||
|
||
item.ResetCurrentRelativePosition();
|
||
}
|
||
base.Initialize(item);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Deinitializes the specified item.
|
||
/// </summary>
|
||
/// <param name="item">The item.</param>
|
||
internal override void Deinitialize(Annotation item)
|
||
{
|
||
if (item != null)
|
||
{
|
||
item.annotationGroup = null;
|
||
item.ResetCurrentRelativePosition();
|
||
}
|
||
base.Deinitialize(item);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Finds an annotation in the collection by name.
|
||
/// </summary>
|
||
/// <param name="name">
|
||
/// Name of the annotation to find.
|
||
/// </param>
|
||
/// <returns>
|
||
/// <see cref="Annotation"/> object, or null (or nothing) if it does not exist.
|
||
/// </returns>
|
||
public override Annotation FindByName(string name)
|
||
{
|
||
foreach(Annotation annotation in this)
|
||
{
|
||
// Compare annotation name
|
||
if(annotation.Name == name)
|
||
{
|
||
return annotation;
|
||
}
|
||
|
||
// Check if annotation is a group
|
||
AnnotationGroup annotationGroup = annotation as AnnotationGroup;
|
||
if(annotationGroup != null)
|
||
{
|
||
Annotation result = annotationGroup.Annotations.FindByName(name);
|
||
if(result != null)
|
||
{
|
||
return result;
|
||
}
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Painting
|
||
|
||
/// <summary>
|
||
/// Paints all annotation objects in the collection.
|
||
/// </summary>
|
||
/// <param name="chartGraph">Chart graphics used for painting.</param>
|
||
/// <param name="drawAnnotationOnly">Indicates that only annotation objects are redrawn.</param>
|
||
[SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", Justification="This parameter is used when compiling for the Microsoft version of Chart")]
|
||
internal void Paint(ChartGraphics chartGraph, bool drawAnnotationOnly)
|
||
{
|
||
#if Microsoft_CONTROL
|
||
ChartPicture chartPicture = this.Chart.chartPicture;
|
||
|
||
// Restore previous background using double buffered bitmap
|
||
if(!chartPicture.isSelectionMode &&
|
||
this.Count > 0 /*&&
|
||
!this.Chart.chartPicture.isPrinting*/)
|
||
{
|
||
chartPicture.backgroundRestored = true;
|
||
Rectangle chartPosition = new Rectangle(0, 0, chartPicture.Width, chartPicture.Height);
|
||
if(chartPicture.nonTopLevelChartBuffer == null || !drawAnnotationOnly)
|
||
{
|
||
// Dispose previous bitmap
|
||
if(chartPicture.nonTopLevelChartBuffer != null)
|
||
{
|
||
chartPicture.nonTopLevelChartBuffer.Dispose();
|
||
chartPicture.nonTopLevelChartBuffer = null;
|
||
}
|
||
|
||
// Copy chart area plotting rectangle from the chart's dubble buffer image into area dubble buffer image
|
||
if (this.Chart.paintBufferBitmap != null &&
|
||
this.Chart.paintBufferBitmap.Size.Width >= chartPosition.Size.Width &&
|
||
this.Chart.paintBufferBitmap.Size.Height >= chartPosition.Size.Height)
|
||
{
|
||
chartPicture.nonTopLevelChartBuffer = this.Chart.paintBufferBitmap.Clone(
|
||
chartPosition, this.Chart.paintBufferBitmap.PixelFormat);
|
||
}
|
||
}
|
||
else if(drawAnnotationOnly && chartPicture.nonTopLevelChartBuffer != null)
|
||
{
|
||
// Restore previous background
|
||
this.Chart.paintBufferBitmapGraphics.DrawImageUnscaled(
|
||
chartPicture.nonTopLevelChartBuffer,
|
||
chartPosition);
|
||
}
|
||
}
|
||
#endif // Microsoft_CONTROL
|
||
|
||
// Draw all annotation objects
|
||
foreach(Annotation annotation in this)
|
||
{
|
||
// Reset calculated relative position
|
||
annotation.ResetCurrentRelativePosition();
|
||
|
||
if(annotation.IsVisible())
|
||
{
|
||
bool resetClip = false;
|
||
|
||
// Check if anchor point ----osiated with plot area is inside the scaleView
|
||
if(annotation.IsAnchorVisible())
|
||
{
|
||
// Set annotation object clipping
|
||
if(annotation.ClipToChartArea.Length > 0 &&
|
||
annotation.ClipToChartArea != Constants.NotSetValue &&
|
||
Chart != null)
|
||
{
|
||
int areaIndex = Chart.ChartAreas.IndexOf(annotation.ClipToChartArea);
|
||
if( areaIndex >= 0 )
|
||
{
|
||
// Get chart area object
|
||
ChartArea chartArea = Chart.ChartAreas[areaIndex];
|
||
chartGraph.SetClip(chartArea.PlotAreaPosition.ToRectangleF());
|
||
resetClip = true;
|
||
}
|
||
}
|
||
|
||
// Start Svg Selection mode
|
||
string url = String.Empty;
|
||
#if !Microsoft_CONTROL
|
||
url = annotation.Url;
|
||
#endif // !Microsoft_CONTROL
|
||
chartGraph.StartHotRegion(
|
||
annotation.ReplaceKeywords(url),
|
||
annotation.ReplaceKeywords(annotation.ToolTip) );
|
||
|
||
// Draw annotation object
|
||
annotation.Paint(Chart, chartGraph);
|
||
|
||
|
||
// End Svg Selection mode
|
||
chartGraph.EndHotRegion( );
|
||
|
||
// Reset clipping region
|
||
if(resetClip)
|
||
{
|
||
chartGraph.ResetClip();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Mouse Events Handlers
|
||
|
||
#if Microsoft_CONTROL
|
||
|
||
/// <summary>
|
||
/// Mouse was double clicked.
|
||
/// </summary>
|
||
internal void OnDoubleClick()
|
||
{
|
||
if(lastClickedAnnotation != null &&
|
||
lastClickedAnnotation.AllowTextEditing)
|
||
{
|
||
TextAnnotation textAnnotation = lastClickedAnnotation as TextAnnotation;
|
||
|
||
if(textAnnotation == null)
|
||
{
|
||
AnnotationGroup group = lastClickedAnnotation as AnnotationGroup;
|
||
|
||
if (group != null)
|
||
{
|
||
// Try to edit text annotation in the group
|
||
foreach (Annotation annot in group.Annotations)
|
||
{
|
||
TextAnnotation groupAnnot = annot as TextAnnotation;
|
||
if (groupAnnot != null &&
|
||
groupAnnot.AllowTextEditing)
|
||
{
|
||
// Get annotation position in relative coordinates
|
||
PointF firstPoint = PointF.Empty;
|
||
PointF anchorPoint = PointF.Empty;
|
||
SizeF size = SizeF.Empty;
|
||
groupAnnot.GetRelativePosition(out firstPoint, out size, out anchorPoint);
|
||
RectangleF textPosition = new RectangleF(firstPoint, size);
|
||
|
||
// Check if last clicked coordinate is inside this text annotation
|
||
if (groupAnnot.GetGraphics() != null &&
|
||
textPosition.Contains(groupAnnot.GetGraphics().GetRelativePoint(this._movingResizingStartPoint)))
|
||
{
|
||
textAnnotation = groupAnnot;
|
||
lastClickedAnnotation = textAnnotation;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if(textAnnotation != null)
|
||
{
|
||
// Start annotation text editing
|
||
textAnnotation.BeginTextEditing();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Checks if specified point is contained by any of the selection handles.
|
||
/// </summary>
|
||
/// <param name="point">Point which is tested in pixel coordinates.</param>
|
||
/// <param name="resizingMode">Handle containing the point or None.</param>
|
||
/// <returns>Annotation that contains the point or Null.</returns>
|
||
internal Annotation HitTestSelectionHandles(PointF point, ref ResizingMode resizingMode)
|
||
{
|
||
Annotation annotation = null;
|
||
|
||
if( Common != null &&
|
||
Common.graph != null)
|
||
{
|
||
PointF pointRel = Common.graph.GetRelativePoint(point);
|
||
foreach(Annotation annot in this)
|
||
{
|
||
// Reset selcted path point
|
||
annot.currentPathPointIndex = -1;
|
||
|
||
// Check if annotation is selected
|
||
if(annot.IsSelected)
|
||
{
|
||
if(annot.selectionRects != null)
|
||
{
|
||
for(int index = 0; index < annot.selectionRects.Length; index++)
|
||
{
|
||
if(!annot.selectionRects[index].IsEmpty &&
|
||
annot.selectionRects[index].Contains(pointRel))
|
||
{
|
||
annotation = annot;
|
||
if(index > (int)ResizingMode.AnchorHandle)
|
||
{
|
||
resizingMode = ResizingMode.MovingPathPoints;
|
||
annot.currentPathPointIndex = index - 9;
|
||
}
|
||
else
|
||
{
|
||
resizingMode = (ResizingMode)index;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return annotation;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Mouse button pressed in the control.
|
||
/// </summary>
|
||
/// <param name="e">Event arguments.</param>
|
||
/// <param name="isHandled">Returns true if event is handled and no further processing required.</param>
|
||
internal void OnMouseDown(MouseEventArgs e, ref bool isHandled)
|
||
{
|
||
// Reset last clicked annotation object and stop text editing
|
||
if(lastClickedAnnotation != null)
|
||
{
|
||
TextAnnotation textAnnotation = lastClickedAnnotation as TextAnnotation;
|
||
if(textAnnotation != null)
|
||
{
|
||
// Stop annotation text editing
|
||
textAnnotation.StopTextEditing();
|
||
}
|
||
lastClickedAnnotation = null;
|
||
}
|
||
|
||
// Check if in annotation placement mode
|
||
if( this.placingAnnotation != null)
|
||
{
|
||
// Process mouse down
|
||
this.placingAnnotation.PlacementMouseDown(new PointF(e.X, e.Y), e.Button);
|
||
|
||
// Set handled flag
|
||
isHandled = true;
|
||
return;
|
||
}
|
||
|
||
// Process only left mouse buttons
|
||
if(e.Button == MouseButtons.Left)
|
||
{
|
||
bool updateRequired = false;
|
||
this._resizingMode = ResizingMode.None;
|
||
|
||
// Check if mouse buton was pressed in any selection handles areas
|
||
Annotation annotation =
|
||
HitTestSelectionHandles(new PointF(e.X, e.Y), ref this._resizingMode);
|
||
|
||
// Check if mouse button was pressed over one of the annotation objects
|
||
if(annotation == null && this.Count > 0)
|
||
{
|
||
HitTestResult result = this.Chart.HitTest(e.X, e.Y, ChartElementType.Annotation);
|
||
if(result != null && result.ChartElementType == ChartElementType.Annotation)
|
||
{
|
||
annotation = (Annotation)result.Object;
|
||
}
|
||
}
|
||
|
||
// Unselect all annotations if mouse clicked outside any annotations
|
||
if(annotation == null || !annotation.IsSelected)
|
||
{
|
||
if((Control.ModifierKeys & Keys.Control) != Keys.Control &&
|
||
(Control.ModifierKeys & Keys.Shift) != Keys.Shift)
|
||
{
|
||
foreach (Annotation annot in this.Chart.Annotations)
|
||
{
|
||
if(annot != annotation && annot.IsSelected)
|
||
{
|
||
annot.IsSelected = false;
|
||
updateRequired = true;
|
||
|
||
// Call selection changed notification
|
||
if (this.Chart != null)
|
||
{
|
||
this.Chart.OnAnnotationSelectionChanged(annot);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Process mouse action in the annotation object
|
||
if(annotation != null)
|
||
{
|
||
// Mouse down event handled
|
||
isHandled = true;
|
||
|
||
// Select/Unselect annotation
|
||
Annotation selectableAnnotation = annotation;
|
||
if(annotation.AnnotationGroup != null)
|
||
{
|
||
// Select annotation group when click on any child annotations
|
||
selectableAnnotation = annotation.AnnotationGroup;
|
||
}
|
||
if(!selectableAnnotation.IsSelected && selectableAnnotation.AllowSelecting)
|
||
{
|
||
selectableAnnotation.IsSelected = true;
|
||
updateRequired = true;
|
||
|
||
// Call selection changed notification
|
||
if (this.Chart != null)
|
||
{
|
||
this.Chart.OnAnnotationSelectionChanged(selectableAnnotation);
|
||
}
|
||
}
|
||
else if((Control.ModifierKeys & Keys.Control) == Keys.Control ||
|
||
(Control.ModifierKeys & Keys.Shift) == Keys.Shift)
|
||
{
|
||
selectableAnnotation.IsSelected = false;
|
||
updateRequired = true;
|
||
|
||
// Call selection changed notification
|
||
if (this.Chart != null)
|
||
{
|
||
this.Chart.OnAnnotationSelectionChanged(selectableAnnotation);
|
||
}
|
||
}
|
||
|
||
// Remember last clicked and selected annotation
|
||
lastClickedAnnotation = annotation;
|
||
|
||
// Rember mouse position
|
||
this._movingResizingStartPoint = new PointF(e.X, e.Y);
|
||
|
||
// Start moving, repositioning or resizing of annotation
|
||
if(annotation.IsSelected)
|
||
{
|
||
// Check if one of selection handles was clicked on
|
||
this._resizingMode = annotation.GetSelectionHandle(this._movingResizingStartPoint);
|
||
if(!annotation.AllowResizing &&
|
||
this._resizingMode >= ResizingMode.TopLeftHandle &&
|
||
this._resizingMode <= ResizingMode.LeftHandle)
|
||
{
|
||
this._resizingMode = ResizingMode.None;
|
||
}
|
||
if(!annotation.AllowAnchorMoving &&
|
||
this._resizingMode == ResizingMode.AnchorHandle)
|
||
{
|
||
this._resizingMode = ResizingMode.None;
|
||
}
|
||
if(this._resizingMode == ResizingMode.None && annotation.AllowMoving)
|
||
{
|
||
// Annotation moving mode
|
||
this._resizingMode = ResizingMode.Moving;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if(this._resizingMode == ResizingMode.None && annotation.AllowMoving)
|
||
{
|
||
// Do not allow moving child annotations inside the group.
|
||
// Only the whole group can be selected, resized or repositioned.
|
||
if (annotation.AnnotationGroup != null)
|
||
{
|
||
// Move the group instead
|
||
lastClickedAnnotation = annotation.AnnotationGroup;
|
||
}
|
||
|
||
// Annotation moving mode
|
||
this._resizingMode = ResizingMode.Moving;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Update chart
|
||
if(updateRequired)
|
||
{
|
||
// Invalidate and update the chart
|
||
this.Chart.Invalidate(true);
|
||
this.Chart.UpdateAnnotations();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Mouse button released in the control.
|
||
/// </summary>
|
||
/// <param name="e">Event arguments.</param>
|
||
internal void OnMouseUp(MouseEventArgs e)
|
||
{
|
||
// Check if in annotation placement mode
|
||
if( this.placingAnnotation != null)
|
||
{
|
||
if(!this.placingAnnotation.PlacementMouseUp(new PointF(e.X, e.Y), e.Button))
|
||
{
|
||
return;
|
||
}
|
||
}
|
||
|
||
if(e.Button == MouseButtons.Left)
|
||
{
|
||
// Reset moving sizing start point
|
||
this._movingResizingStartPoint = PointF.Empty;
|
||
this._resizingMode = ResizingMode.None;
|
||
}
|
||
|
||
// Loop through all annotation objects
|
||
for(int index = 0; index < this.Count; index++)
|
||
{
|
||
Annotation annotation = this[index];
|
||
|
||
// NOTE: Automatic deleting feature was disabled. -AG.
|
||
/*
|
||
// Delete all annotation objects moved outside clipping region
|
||
if( annotation.outsideClipRegion )
|
||
{
|
||
this.List.RemoveAt(index);
|
||
--index;
|
||
}
|
||
*/
|
||
|
||
// Reset start position/location fields
|
||
annotation.startMovePositionRel = RectangleF.Empty;
|
||
annotation.startMoveAnchorLocationRel = PointF.Empty;
|
||
if(annotation.startMovePathRel != null)
|
||
{
|
||
annotation.startMovePathRel.Dispose();
|
||
annotation.startMovePathRel = null;
|
||
}
|
||
|
||
// Fire position changed event
|
||
if( annotation.positionChanged )
|
||
{
|
||
annotation.positionChanged = false;
|
||
if (this.Chart != null)
|
||
{
|
||
this.Chart.OnAnnotationPositionChanged(annotation);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Mouse moved in the control.
|
||
/// </summary>
|
||
/// <param name="e">Event arguments.</param>
|
||
internal void OnMouseMove(MouseEventArgs e)
|
||
{
|
||
// Check if in annotation placement mode
|
||
if(this.placingAnnotation != null)
|
||
{
|
||
System.Windows.Forms.Cursor newCursor = this.Chart.Cursor;
|
||
if(this.placingAnnotation.IsValidPlacementPosition(e.X, e.Y))
|
||
{
|
||
newCursor = Cursors.Cross;
|
||
}
|
||
else
|
||
{
|
||
newCursor = this.Chart.defaultCursor;
|
||
}
|
||
|
||
// Set current chart cursor
|
||
if (newCursor != this.Chart.Cursor)
|
||
{
|
||
System.Windows.Forms.Cursor tmpCursor = this.Chart.defaultCursor;
|
||
this.Chart.Cursor = newCursor;
|
||
this.Chart.defaultCursor = tmpCursor;
|
||
}
|
||
|
||
this.placingAnnotation.PlacementMouseMove(new PointF(e.X, e.Y));
|
||
|
||
return;
|
||
}
|
||
|
||
// Check if currently resizing/moving annotation
|
||
if(!this._movingResizingStartPoint.IsEmpty &&
|
||
this._resizingMode != ResizingMode.None)
|
||
{
|
||
// Calculate how far the mouse was moved
|
||
SizeF moveDistance = new SizeF(
|
||
this._movingResizingStartPoint.X - e.X,
|
||
this._movingResizingStartPoint.Y - e.Y );
|
||
|
||
// Update location of all selected annotation objects
|
||
foreach(Annotation annot in this)
|
||
{
|
||
if(annot.IsSelected &&
|
||
( (this._resizingMode == ResizingMode.MovingPathPoints && annot.AllowPathEditing) ||
|
||
(this._resizingMode == ResizingMode.Moving && annot.AllowMoving) ||
|
||
(this._resizingMode == ResizingMode.AnchorHandle && annot.AllowAnchorMoving) ||
|
||
(this._resizingMode >= ResizingMode.TopLeftHandle && this._resizingMode <= ResizingMode.LeftHandle && annot.AllowResizing) ) )
|
||
{
|
||
annot.AdjustLocationSize(moveDistance, this._resizingMode, true, true);
|
||
}
|
||
}
|
||
|
||
// Move last clicked non-selected annotation
|
||
if(lastClickedAnnotation != null &&
|
||
!lastClickedAnnotation.IsSelected)
|
||
{
|
||
if(this._resizingMode == ResizingMode.Moving &&
|
||
lastClickedAnnotation.AllowMoving)
|
||
{
|
||
lastClickedAnnotation.AdjustLocationSize(moveDistance, this._resizingMode, true, true);
|
||
}
|
||
}
|
||
|
||
// Invalidate and update the chart
|
||
this.Chart.Invalidate(true);
|
||
this.Chart.UpdateAnnotations();
|
||
}
|
||
else if(this.Count > 0)
|
||
{
|
||
// Check if currently placing annotation from the UserInterface
|
||
bool process = true;
|
||
|
||
if(process)
|
||
{
|
||
// Check if mouse pointer is over the annotation selection handle
|
||
ResizingMode currentResizingMode = ResizingMode.None;
|
||
Annotation annotation =
|
||
HitTestSelectionHandles(new PointF(e.X, e.Y), ref currentResizingMode);
|
||
|
||
// Check if mouse pointer over the annotation object movable area
|
||
if(annotation == null)
|
||
{
|
||
HitTestResult result = this.Chart.HitTest(e.X, e.Y, ChartElementType.Annotation);
|
||
if(result != null && result.ChartElementType == ChartElementType.Annotation)
|
||
{
|
||
annotation = (Annotation)result.Object;
|
||
if(annotation != null)
|
||
{
|
||
// Check if annotation is in the collection
|
||
if(this.Contains(annotation))
|
||
{
|
||
currentResizingMode = ResizingMode.Moving;
|
||
if(annotation.AllowMoving == false)
|
||
{
|
||
// Movement is not allowed
|
||
annotation = null;
|
||
currentResizingMode = ResizingMode.None;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// Set mouse cursor
|
||
SetResizingCursor(annotation, currentResizingMode);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Sets mouse cursor shape.
|
||
/// </summary>
|
||
/// <param name="annotation">Annotation object.</param>
|
||
/// <param name="currentResizingMode">Resizing mode.</param>
|
||
private void SetResizingCursor(Annotation annotation, ResizingMode currentResizingMode)
|
||
{
|
||
// Change current cursor
|
||
if(this.Chart != null)
|
||
{
|
||
System.Windows.Forms.Cursor newCursor = this.Chart.Cursor;
|
||
if(annotation != null)
|
||
{
|
||
if(currentResizingMode == ResizingMode.MovingPathPoints &&
|
||
annotation.AllowPathEditing)
|
||
{
|
||
newCursor = Cursors.Cross;
|
||
}
|
||
|
||
if(currentResizingMode == ResizingMode.Moving &&
|
||
annotation.AllowMoving)
|
||
{
|
||
newCursor = Cursors.SizeAll;
|
||
}
|
||
|
||
if(currentResizingMode == ResizingMode.AnchorHandle &&
|
||
annotation.AllowAnchorMoving)
|
||
{
|
||
newCursor = Cursors.Cross;
|
||
}
|
||
|
||
if(currentResizingMode != ResizingMode.Moving &&
|
||
annotation.AllowResizing)
|
||
{
|
||
if(annotation.SelectionPointsStyle == SelectionPointsStyle.TwoPoints)
|
||
{
|
||
if(currentResizingMode == ResizingMode.TopLeftHandle ||
|
||
currentResizingMode == ResizingMode.BottomRightHandle)
|
||
{
|
||
newCursor = Cursors.Cross;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if(currentResizingMode == ResizingMode.TopLeftHandle ||
|
||
currentResizingMode == ResizingMode.BottomRightHandle)
|
||
{
|
||
newCursor = Cursors.SizeNWSE;
|
||
}
|
||
else if(currentResizingMode == ResizingMode.TopRightHandle ||
|
||
currentResizingMode == ResizingMode.BottomLeftHandle)
|
||
{
|
||
newCursor = Cursors.SizeNESW;
|
||
}
|
||
else if(currentResizingMode == ResizingMode.TopHandle ||
|
||
currentResizingMode == ResizingMode.BottomHandle)
|
||
{
|
||
newCursor = Cursors.SizeNS;
|
||
}
|
||
else if(currentResizingMode == ResizingMode.LeftHandle ||
|
||
currentResizingMode == ResizingMode.RightHandle)
|
||
{
|
||
newCursor = Cursors.SizeWE;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
newCursor = this.Chart.defaultCursor;
|
||
}
|
||
|
||
// Set current chart cursor
|
||
if (newCursor != this.Chart.Cursor)
|
||
{
|
||
System.Windows.Forms.Cursor tmpCursor = this.Chart.defaultCursor;
|
||
this.Chart.Cursor = newCursor;
|
||
this.Chart.defaultCursor = tmpCursor;
|
||
}
|
||
}
|
||
}
|
||
|
||
#endif // Microsoft_CONTROL
|
||
|
||
#endregion
|
||
|
||
#region Event handlers
|
||
internal void ChartAreaNameReferenceChanged(object sender, NameReferenceChangedEventArgs e)
|
||
{
|
||
// If all the chart areas are removed and then a new one is inserted - Annotations don't get bound to it by default
|
||
if (e.OldElement == null)
|
||
return;
|
||
|
||
foreach (Annotation annotation in this)
|
||
{
|
||
if (annotation.ClipToChartArea == e.OldName)
|
||
annotation.ClipToChartArea = e.NewName;
|
||
|
||
AnnotationGroup group = annotation as AnnotationGroup;
|
||
if (group != null)
|
||
{
|
||
group.Annotations.ChartAreaNameReferenceChanged(sender, e);
|
||
}
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
}
|
||
}
|