You've already forked linux-packaging-mono
3496 lines
116 KiB
C#
3496 lines
116 KiB
C#
|
|
//-------------------------------------------------------------
|
|||
|
|
// <copyright company=<3D>Microsoft Corporation<6F>>
|
|||
|
|
// Copyright <20> Microsoft Corporation. All Rights Reserved.
|
|||
|
|
// </copyright>
|
|||
|
|
//-------------------------------------------------------------
|
|||
|
|
// @owner=alexgor, deliant
|
|||
|
|
//=================================================================
|
|||
|
|
// File: Selection.cs
|
|||
|
|
//
|
|||
|
|
// Namespace: DataVisualization.Charting
|
|||
|
|
//
|
|||
|
|
// Classes: Selection, HitTestResult, ToolTipEventArgs,
|
|||
|
|
// HotRegionElement, Hot Region
|
|||
|
|
//
|
|||
|
|
// Purpose: This file contains methods used for Win Form selection
|
|||
|
|
//
|
|||
|
|
// Reviewed: AG - Oct 21
|
|||
|
|
//
|
|||
|
|
//===================================================================
|
|||
|
|
|
|||
|
|
|
|||
|
|
#region Used namespaces
|
|||
|
|
|
|||
|
|
using System;
|
|||
|
|
using System.Drawing;
|
|||
|
|
using System.Drawing.Drawing2D;
|
|||
|
|
using System.Collections;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.Globalization;
|
|||
|
|
using System.Diagnostics.CodeAnalysis;
|
|||
|
|
using System.ComponentModel.Design;
|
|||
|
|
using System.ComponentModel;
|
|||
|
|
using System.Text;
|
|||
|
|
using System.Collections.ObjectModel;
|
|||
|
|
|
|||
|
|
#if Microsoft_CONTROL
|
|||
|
|
using System.Windows.Forms;
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#if Microsoft_CONTROL
|
|||
|
|
namespace System.Windows.Forms.DataVisualization.Charting
|
|||
|
|
#else
|
|||
|
|
namespace System.Web.UI.DataVisualization.Charting
|
|||
|
|
#endif
|
|||
|
|
{
|
|||
|
|
#region Enumerations
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Plase keep the folowing enumaration in chart layering order - ex. ChartArea is under DataPoint
|
|||
|
|
/// <summary>
|
|||
|
|
/// An enumeration of types of Chart Element.
|
|||
|
|
/// </summary>
|
|||
|
|
public enum ChartElementType
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// No chart element.
|
|||
|
|
/// </summary>
|
|||
|
|
Nothing,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// The title of a chart.
|
|||
|
|
/// </summary>
|
|||
|
|
Title,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Plotting area (chart area excluding axes, labels, etc.).
|
|||
|
|
/// Also excludes the regions that data points may occupy.
|
|||
|
|
/// </summary>
|
|||
|
|
PlottingArea,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// An Axis object.
|
|||
|
|
/// </summary>
|
|||
|
|
Axis,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Any major or minor tick mark.
|
|||
|
|
/// </summary>
|
|||
|
|
TickMarks,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Any major or minor grid line (both vertical or horizontal).
|
|||
|
|
/// </summary>
|
|||
|
|
Gridlines,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// A StripLine object.
|
|||
|
|
/// </summary>
|
|||
|
|
StripLines,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Axis label Image.
|
|||
|
|
/// </summary>
|
|||
|
|
AxisLabelImage,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Axis labels
|
|||
|
|
/// </summary>
|
|||
|
|
AxisLabels,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Axis title
|
|||
|
|
/// </summary>
|
|||
|
|
AxisTitle,
|
|||
|
|
|
|||
|
|
|
|||
|
|
#if Microsoft_CONTROL
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// A scrollbar tracking thumb.
|
|||
|
|
/// </summary>
|
|||
|
|
ScrollBarThumbTracker,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// A scrollbar small decrement button. A "down arrow"
|
|||
|
|
/// button for a vertical scrollbar, or a "left arrow"
|
|||
|
|
/// button for a horizontal scroll bar.
|
|||
|
|
/// </summary>
|
|||
|
|
ScrollBarSmallDecrement,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// A scrollbar small increment button. An "up arrow"
|
|||
|
|
/// button for a vertical scrollbar, or a "right arrow"
|
|||
|
|
/// button for a horizontal scroll bar.
|
|||
|
|
/// </summary>
|
|||
|
|
ScrollBarSmallIncrement,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// The background of a scrollbar that will result in
|
|||
|
|
/// a large decrement in the scale view size when clicked.
|
|||
|
|
/// This is the background below the thumb for
|
|||
|
|
/// a vertical scrollbar, and to the left of
|
|||
|
|
/// the thumb for a horizontal scrollbar.
|
|||
|
|
/// </summary>
|
|||
|
|
ScrollBarLargeDecrement,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// The background of a scrollbar that will result in
|
|||
|
|
/// a large increment in the scale view size when clicked.
|
|||
|
|
/// This is the background above the thumb for
|
|||
|
|
/// a vertical scrollbar, and to the right of
|
|||
|
|
/// the thumb for a horizontal scrollbar.
|
|||
|
|
/// </summary>
|
|||
|
|
ScrollBarLargeIncrement,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// The zoom reset button of a scrollbar.
|
|||
|
|
/// </summary>
|
|||
|
|
ScrollBarZoomReset,
|
|||
|
|
|
|||
|
|
#endif // Microsoft_CONTROL
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// A DataPoint object.
|
|||
|
|
/// </summary>
|
|||
|
|
DataPoint,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Series data point label.
|
|||
|
|
/// </summary>
|
|||
|
|
DataPointLabel,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// The area inside a Legend object. Does not include
|
|||
|
|
/// the space occupied by legend items.
|
|||
|
|
/// </summary>
|
|||
|
|
LegendArea,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Legend title.
|
|||
|
|
/// </summary>
|
|||
|
|
LegendTitle,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Legend header.
|
|||
|
|
/// </summary>
|
|||
|
|
LegendHeader,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// A LegendItem object.
|
|||
|
|
/// </summary>
|
|||
|
|
LegendItem,
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Chart annotation object.
|
|||
|
|
/// </summary>
|
|||
|
|
Annotation,
|
|||
|
|
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Enumeration (Flag) used for processing chart types.
|
|||
|
|
/// </summary>
|
|||
|
|
[Flags]
|
|||
|
|
internal enum ProcessMode
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// Paint mode
|
|||
|
|
/// </summary>
|
|||
|
|
Paint = 1,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Selection mode. Collection of hot regions has to be created.
|
|||
|
|
/// </summary>
|
|||
|
|
HotRegions = 2,
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Used for image maps
|
|||
|
|
/// </summary>
|
|||
|
|
ImageMaps = 4
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// This class presents item in
|
|||
|
|
/// the collection of hot regions.
|
|||
|
|
/// </summary>
|
|||
|
|
internal class HotRegion : IDisposable
|
|||
|
|
{
|
|||
|
|
#region Fields
|
|||
|
|
|
|||
|
|
// Private data members, which store properties values
|
|||
|
|
private GraphicsPath _path = null;
|
|||
|
|
private bool _relativeCoordinates = true;
|
|||
|
|
private RectangleF _boundingRectangle = RectangleF.Empty;
|
|||
|
|
private object _selectedObject = null;
|
|||
|
|
private int _pointIndex = -1;
|
|||
|
|
private string _seriesName = "";
|
|||
|
|
private ChartElementType _type = ChartElementType.Nothing;
|
|||
|
|
|
|||
|
|
|
|||
|
|
private object _selectedSubObject = null;
|
|||
|
|
|
|||
|
|
|
|||
|
|
#endregion // Fields
|
|||
|
|
|
|||
|
|
#region Properties
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Region is Graphics path
|
|||
|
|
/// </summary>
|
|||
|
|
internal GraphicsPath Path
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _path;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_path = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Relative coordinates are used
|
|||
|
|
/// to define region
|
|||
|
|
/// </summary>
|
|||
|
|
internal bool RelativeCoordinates
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _relativeCoordinates;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_relativeCoordinates = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Bounding Rectangle of an shape
|
|||
|
|
/// </summary>
|
|||
|
|
internal RectangleF BoundingRectangle
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _boundingRectangle;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_boundingRectangle = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Object which is presented with this region
|
|||
|
|
/// </summary>
|
|||
|
|
internal object SelectedObject
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _selectedObject;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_selectedObject = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Sub-Object which is presented with this region
|
|||
|
|
/// </summary>
|
|||
|
|
internal object SelectedSubObject
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _selectedSubObject;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_selectedSubObject = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Index of the data point which is presented with this region
|
|||
|
|
/// </summary>
|
|||
|
|
internal int PointIndex
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _pointIndex;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_pointIndex = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Name of the series which is presented with the region
|
|||
|
|
/// </summary>
|
|||
|
|
internal string SeriesName
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _seriesName;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_seriesName = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Chart Element AxisName
|
|||
|
|
/// </summary>
|
|||
|
|
internal ChartElementType Type
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _type;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_type = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion // Properties
|
|||
|
|
|
|||
|
|
#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 virtual void Dispose(bool disposing)
|
|||
|
|
{
|
|||
|
|
if (disposing)
|
|||
|
|
{
|
|||
|
|
if (_path != null)
|
|||
|
|
{
|
|||
|
|
_path.Dispose();
|
|||
|
|
_path = null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
|||
|
|
/// </summary>
|
|||
|
|
public void Dispose()
|
|||
|
|
{
|
|||
|
|
Dispose(true);
|
|||
|
|
GC.SuppressFinalize(this);
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region Methods
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns>
|
|||
|
|
/// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
|
|||
|
|
/// </returns>
|
|||
|
|
public override string ToString()
|
|||
|
|
{
|
|||
|
|
string objectType = this.SelectedObject != null ? this.SelectedObject.ToString() : "null";
|
|||
|
|
if (this.SelectedObject == null && !String.IsNullOrEmpty(this.SeriesName))
|
|||
|
|
{
|
|||
|
|
objectType = this.SeriesName;
|
|||
|
|
}
|
|||
|
|
return String.Format(CultureInfo.CurrentCulture, "{0} of {1}", this.Type, objectType);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion //Methods
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// This class is used to fill and
|
|||
|
|
/// manage collection with Hot Regions
|
|||
|
|
/// </summary>
|
|||
|
|
internal class HotRegionsList : IDisposable
|
|||
|
|
{
|
|||
|
|
#region Fields
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Process chart mode Flag
|
|||
|
|
/// </summary>
|
|||
|
|
private ProcessMode _processChartMode = ProcessMode.Paint;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Collection with Hor Region Elements
|
|||
|
|
/// </summary>
|
|||
|
|
private System.Collections.ArrayList _regionList = new ArrayList();
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Reference to the common elements object
|
|||
|
|
/// </summary>
|
|||
|
|
private CommonElements _common = null;
|
|||
|
|
|
|||
|
|
#if Microsoft_CONTROL
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// True if hit test function is called
|
|||
|
|
/// </summary>
|
|||
|
|
internal bool hitTestCalled = false;
|
|||
|
|
|
|||
|
|
#endif // Microsoft_CONTROL
|
|||
|
|
|
|||
|
|
#endregion // Fields
|
|||
|
|
|
|||
|
|
#region Properties
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Flag used for processing chart types. It could
|
|||
|
|
/// be Paint, HotRegion or both mode.
|
|||
|
|
/// </summary>
|
|||
|
|
internal ProcessMode ProcessChartMode
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _processChartMode;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_processChartMode = value;
|
|||
|
|
if(this._common != null)
|
|||
|
|
{
|
|||
|
|
this._common.processModePaint =
|
|||
|
|
(_processChartMode & ProcessMode.Paint ) == ProcessMode.Paint;
|
|||
|
|
this._common.processModeRegions =
|
|||
|
|
( _processChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions ||
|
|||
|
|
( _processChartMode & ProcessMode.ImageMaps ) == ProcessMode.ImageMaps;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Collection with Hor Region Elements
|
|||
|
|
/// </summary>
|
|||
|
|
internal ArrayList List
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _regionList;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion // Properties
|
|||
|
|
|
|||
|
|
#region Methods
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Constructor
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="common">Reference to the CommonElements</param>
|
|||
|
|
internal HotRegionsList( CommonElements common )
|
|||
|
|
{
|
|||
|
|
this._common = common;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Add hot region to the collection.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="rectSize">Rectangle which presents an Hot Region</param>
|
|||
|
|
/// <param name="point">Data Point</param>
|
|||
|
|
/// <param name="seriesName">Data Series</param>
|
|||
|
|
/// <param name="pointIndex">Index of an Data Point in the series</param>
|
|||
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
|
|||
|
|
public void AddHotRegion(
|
|||
|
|
RectangleF rectSize,
|
|||
|
|
DataPoint point,
|
|||
|
|
string seriesName,
|
|||
|
|
int pointIndex
|
|||
|
|
)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
#if !Microsoft_CONTROL
|
|||
|
|
if( ( ProcessChartMode & ProcessMode.ImageMaps ) == ProcessMode.ImageMaps )
|
|||
|
|
{
|
|||
|
|
if (_common.ChartPicture.IsMapEnabled == true)
|
|||
|
|
{
|
|||
|
|
if(point.ToolTip.Length > 0 ||
|
|||
|
|
point.Url.Length > 0 ||
|
|||
|
|
point.MapAreaAttributes.Length > 0 ||
|
|||
|
|
point.PostBackValue.Length > 0
|
|||
|
|
)
|
|||
|
|
{
|
|||
|
|
MapArea area = new MapArea(
|
|||
|
|
point.ReplaceKeywords(point.ToolTip),
|
|||
|
|
point.ReplaceKeywords(point.Url),
|
|||
|
|
point.ReplaceKeywords(point.MapAreaAttributes),
|
|||
|
|
point.ReplaceKeywords(point.PostBackValue),
|
|||
|
|
rectSize,
|
|||
|
|
point.Tag);
|
|||
|
|
area.IsCustom = false;
|
|||
|
|
_common.ChartPicture.MapAreas.Insert(0, area);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#endif // !Microsoft_CONTROL
|
|||
|
|
|
|||
|
|
if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
|
|||
|
|
{
|
|||
|
|
HotRegion region = new HotRegion();
|
|||
|
|
|
|||
|
|
region.BoundingRectangle = rectSize;
|
|||
|
|
region.SeriesName = seriesName;
|
|||
|
|
region.PointIndex = pointIndex;
|
|||
|
|
region.Type = ChartElementType.DataPoint;
|
|||
|
|
region.RelativeCoordinates = true;
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Use index of the original data point
|
|||
|
|
if(point != null && point.IsCustomPropertySet("OriginalPointIndex"))
|
|||
|
|
{
|
|||
|
|
region.PointIndex = int.Parse(point["OriginalPointIndex"], CultureInfo.InvariantCulture);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
_regionList.Add( region );
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Adds the hot region.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="path">Bounding GraphicsPath.</param>
|
|||
|
|
/// <param name="relativePath">if set to <c>true</c> the is relative path.</param>
|
|||
|
|
/// <param name="graph">Chart Graphics Object</param>
|
|||
|
|
/// <param name="point">Selected data point</param>
|
|||
|
|
/// <param name="seriesName">Name of the series.</param>
|
|||
|
|
/// <param name="pointIndex">Index of the point.</param>
|
|||
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "graph")]
|
|||
|
|
internal void AddHotRegion(
|
|||
|
|
GraphicsPath path,
|
|||
|
|
bool relativePath,
|
|||
|
|
ChartGraphics graph,
|
|||
|
|
DataPoint point,
|
|||
|
|
string seriesName,
|
|||
|
|
int pointIndex
|
|||
|
|
)
|
|||
|
|
{
|
|||
|
|
if( path == null )
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
#if !Microsoft_CONTROL
|
|||
|
|
if( ( ProcessChartMode & ProcessMode.ImageMaps ) == ProcessMode.ImageMaps )
|
|||
|
|
{
|
|||
|
|
if (_common.ChartPicture.IsMapEnabled == true)
|
|||
|
|
{
|
|||
|
|
if(point.ToolTip.Length > 0 ||
|
|||
|
|
point.Url.Length > 0 ||
|
|||
|
|
point.MapAreaAttributes.Length > 0 ||
|
|||
|
|
point.PostBackValue.Length > 0
|
|||
|
|
)
|
|||
|
|
{
|
|||
|
|
int prevMapAreaCount = _common.ChartPicture.MapAreas.Count;
|
|||
|
|
_common.ChartPicture.MapAreas.InsertPath(
|
|||
|
|
0,
|
|||
|
|
point.ReplaceKeywords(point.ToolTip),
|
|||
|
|
point.ReplaceKeywords(point.Url),
|
|||
|
|
point.ReplaceKeywords(point.MapAreaAttributes),
|
|||
|
|
point.ReplaceKeywords(point.PostBackValue),
|
|||
|
|
path,
|
|||
|
|
!relativePath,
|
|||
|
|
graph
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Set map area type
|
|||
|
|
for (int i = 0; i < _common.ChartPicture.MapAreas.Count - prevMapAreaCount; i++)
|
|||
|
|
((IChartMapArea)_common.ChartPicture.MapAreas[i]).Tag = ((IChartMapArea)point).Tag;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#endif // !Microsoft_CONTROL
|
|||
|
|
|
|||
|
|
if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
HotRegion region = new HotRegion();
|
|||
|
|
|
|||
|
|
region.SeriesName = seriesName;
|
|||
|
|
region.PointIndex = pointIndex;
|
|||
|
|
region.Type = ChartElementType.DataPoint;
|
|||
|
|
region.Path = (GraphicsPath)path.Clone();
|
|||
|
|
region.BoundingRectangle = path.GetBounds();
|
|||
|
|
region.RelativeCoordinates = relativePath;
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Use index of the original data point
|
|||
|
|
if(point != null && point.IsCustomPropertySet("OriginalPointIndex"))
|
|||
|
|
{
|
|||
|
|
region.PointIndex = int.Parse(point["OriginalPointIndex"], CultureInfo.InvariantCulture);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
_regionList.Add( region );
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Adds the hot region.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="insertIndex">Position where to insert element. Used for image maps only</param>
|
|||
|
|
/// <param name="path">Bounding GraphicsPath.</param>
|
|||
|
|
/// <param name="relativePath">if set to <c>true</c> the is relative path.</param>
|
|||
|
|
/// <param name="graph">Chart Graphics Object</param>
|
|||
|
|
/// <param name="point">Selected data point</param>
|
|||
|
|
/// <param name="seriesName">Name of the series.</param>
|
|||
|
|
/// <param name="pointIndex">Index of the point.</param>
|
|||
|
|
[
|
|||
|
|
System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "graph"),
|
|||
|
|
System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "insertIndex")
|
|||
|
|
]
|
|||
|
|
internal void AddHotRegion(
|
|||
|
|
int insertIndex,
|
|||
|
|
GraphicsPath path,
|
|||
|
|
bool relativePath,
|
|||
|
|
ChartGraphics graph,
|
|||
|
|
DataPoint point,
|
|||
|
|
string seriesName,
|
|||
|
|
int pointIndex
|
|||
|
|
)
|
|||
|
|
{
|
|||
|
|
#if !Microsoft_CONTROL
|
|||
|
|
if( ( ProcessChartMode & ProcessMode.ImageMaps ) == ProcessMode.ImageMaps )
|
|||
|
|
{
|
|||
|
|
if (_common.ChartPicture.IsMapEnabled == true)
|
|||
|
|
{
|
|||
|
|
if(point.ToolTip.Length > 0 ||
|
|||
|
|
point.Url.Length > 0 ||
|
|||
|
|
point.MapAreaAttributes.Length > 0 ||
|
|||
|
|
point.PostBackValue.Length > 0)
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
int prevMapAreaCount = _common.ChartPicture.MapAreas.Count;
|
|||
|
|
|
|||
|
|
_common.ChartPicture.MapAreas.InsertPath(
|
|||
|
|
insertIndex,
|
|||
|
|
point.ReplaceKeywords(point.ToolTip),
|
|||
|
|
point.ReplaceKeywords(point.Url),
|
|||
|
|
point.ReplaceKeywords(point.MapAreaAttributes),
|
|||
|
|
point.ReplaceKeywords(point.PostBackValue),
|
|||
|
|
path,
|
|||
|
|
!relativePath,
|
|||
|
|
graph
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
// Set map area type
|
|||
|
|
for (int i = insertIndex; i < _common.ChartPicture.MapAreas.Count - prevMapAreaCount; i++)
|
|||
|
|
((IChartMapArea)_common.ChartPicture.MapAreas[i]).Tag = ((IChartMapArea)point).Tag;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#endif // !Microsoft_CONTROL
|
|||
|
|
|
|||
|
|
if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
HotRegion region = new HotRegion();
|
|||
|
|
|
|||
|
|
region.SeriesName = seriesName;
|
|||
|
|
region.PointIndex = pointIndex;
|
|||
|
|
region.Type = ChartElementType.DataPoint;
|
|||
|
|
region.Path = (GraphicsPath)path.Clone();
|
|||
|
|
region.BoundingRectangle = path.GetBounds();
|
|||
|
|
region.RelativeCoordinates = relativePath;
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Use index of the original data point
|
|||
|
|
if(point != null && point.IsCustomPropertySet("OriginalPointIndex"))
|
|||
|
|
{
|
|||
|
|
region.PointIndex = int.Parse(point["OriginalPointIndex"], CultureInfo.InvariantCulture);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
_regionList.Add( region );
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Add hot region to the collection.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="path">Graphics path which presents hot region</param>
|
|||
|
|
/// <param name="relativePath">Graphics path uses relative or absolute coordinates</param>
|
|||
|
|
/// <param name="coord">Coordinates which defines polygon (Graphics Path). Used for image maps</param>
|
|||
|
|
/// <param name="point">Selected data point</param>
|
|||
|
|
/// <param name="seriesName">Data Series</param>
|
|||
|
|
/// <param name="pointIndex">Index of an Data Point in the series</param>
|
|||
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "coord")]
|
|||
|
|
internal void AddHotRegion( GraphicsPath path, bool relativePath, float [] coord, DataPoint point, string seriesName, int pointIndex )
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
#if !Microsoft_CONTROL
|
|||
|
|
if( ( ProcessChartMode & ProcessMode.ImageMaps ) == ProcessMode.ImageMaps )
|
|||
|
|
{
|
|||
|
|
if (_common.ChartPicture.IsMapEnabled == true)
|
|||
|
|
{
|
|||
|
|
if(point.ToolTip.Length > 0 ||
|
|||
|
|
point.Url.Length > 0 ||
|
|||
|
|
point.MapAreaAttributes.Length > 0 ||
|
|||
|
|
point.PostBackValue.Length > 0)
|
|||
|
|
{
|
|||
|
|
MapArea area = new MapArea(
|
|||
|
|
MapAreaShape.Polygon,
|
|||
|
|
point.ReplaceKeywords(point.ToolTip),
|
|||
|
|
point.ReplaceKeywords(point.Url),
|
|||
|
|
point.ReplaceKeywords(point.MapAreaAttributes),
|
|||
|
|
point.ReplaceKeywords(point.PostBackValue),
|
|||
|
|
coord,
|
|||
|
|
point.Tag);
|
|||
|
|
area.IsCustom = false;
|
|||
|
|
_common.ChartPicture.MapAreas.Insert(0,area);
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#endif // !Microsoft_CONTROL
|
|||
|
|
|
|||
|
|
if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
HotRegion region = new HotRegion();
|
|||
|
|
|
|||
|
|
region.SeriesName = seriesName;
|
|||
|
|
region.PointIndex = pointIndex;
|
|||
|
|
region.Type = ChartElementType.DataPoint;
|
|||
|
|
region.Path = (GraphicsPath)path.Clone();
|
|||
|
|
region.BoundingRectangle = path.GetBounds();
|
|||
|
|
region.RelativeCoordinates = relativePath;
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Use index of the original data point
|
|||
|
|
if(point != null && point.IsCustomPropertySet("OriginalPointIndex"))
|
|||
|
|
{
|
|||
|
|
region.PointIndex = int.Parse(point["OriginalPointIndex"], CultureInfo.InvariantCulture);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
_regionList.Add( region );
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Add Hot region to the collection.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="insertIndex">Position where to insert element. Used for image maps only</param>
|
|||
|
|
/// <param name="graph">Chart Graphics Object</param>
|
|||
|
|
/// <param name="x">x coordinate.</param>
|
|||
|
|
/// <param name="y">y coordinate.</param>
|
|||
|
|
/// <param name="radius">The radius.</param>
|
|||
|
|
/// <param name="point">Selected data point</param>
|
|||
|
|
/// <param name="seriesName">Data Series</param>
|
|||
|
|
/// <param name="pointIndex">Index of an Data Point in the series</param>
|
|||
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "insertIndex")]
|
|||
|
|
internal void AddHotRegion( int insertIndex, ChartGraphics graph, float x, float y, float radius, DataPoint point, string seriesName, int pointIndex )
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
#if !Microsoft_CONTROL
|
|||
|
|
if( ( ProcessChartMode & ProcessMode.ImageMaps ) == ProcessMode.ImageMaps )
|
|||
|
|
{
|
|||
|
|
if (_common.ChartPicture.IsMapEnabled == true)
|
|||
|
|
{
|
|||
|
|
if(point.ToolTip.Length > 0 ||
|
|||
|
|
point.Url.Length > 0 ||
|
|||
|
|
point.MapAreaAttributes.Length > 0 ||
|
|||
|
|
point.PostBackValue.Length > 0 )
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
float[] circCoord = new float[3];
|
|||
|
|
circCoord[0] = x;
|
|||
|
|
circCoord[1] = y;
|
|||
|
|
circCoord[2] = radius;
|
|||
|
|
|
|||
|
|
MapArea area = new MapArea(
|
|||
|
|
MapAreaShape.Circle,
|
|||
|
|
point.ReplaceKeywords(point.ToolTip),
|
|||
|
|
point.ReplaceKeywords(point.Url),
|
|||
|
|
point.ReplaceKeywords(point.MapAreaAttributes),
|
|||
|
|
point.ReplaceKeywords(point.PostBackValue),
|
|||
|
|
circCoord,
|
|||
|
|
point.Tag);
|
|||
|
|
area.IsCustom = false;
|
|||
|
|
// Insert area
|
|||
|
|
_common.ChartPicture.MapAreas.Insert(insertIndex,area);
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#endif // !Microsoft_CONTROL
|
|||
|
|
|
|||
|
|
if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
|
|||
|
|
{
|
|||
|
|
HotRegion region = new HotRegion();
|
|||
|
|
|
|||
|
|
PointF circleCenter = graph.GetAbsolutePoint( new PointF( x, y ) );
|
|||
|
|
SizeF circleRadius = graph.GetAbsoluteSize( new SizeF( radius, radius ) );
|
|||
|
|
|
|||
|
|
GraphicsPath path = new GraphicsPath();
|
|||
|
|
path.AddEllipse(
|
|||
|
|
circleCenter.X - circleRadius.Width,
|
|||
|
|
circleCenter.Y - circleRadius.Width,
|
|||
|
|
2 * circleRadius.Width,
|
|||
|
|
2 * circleRadius.Width
|
|||
|
|
);
|
|||
|
|
region.BoundingRectangle = path.GetBounds();
|
|||
|
|
region.SeriesName = seriesName;
|
|||
|
|
region.Type = ChartElementType.DataPoint;
|
|||
|
|
region.PointIndex = pointIndex;
|
|||
|
|
region.Path = path;
|
|||
|
|
region.RelativeCoordinates = false;
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Use index of the original data point
|
|||
|
|
if(point != null && point.IsCustomPropertySet("OriginalPointIndex"))
|
|||
|
|
{
|
|||
|
|
region.PointIndex = int.Parse(point["OriginalPointIndex"], CultureInfo.InvariantCulture);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
_regionList.Add( region );
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Add Hot region to the collection.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="rectArea">Hot Region rectangle</param>
|
|||
|
|
/// <param name="toolTip">Tool Tip Text</param>
|
|||
|
|
/// <param name="hRef">HRef string</param>
|
|||
|
|
/// <param name="mapAreaAttributes">Map area Attribute string</param>
|
|||
|
|
/// <param name="postBackValue">The post back value associated with this item</param>
|
|||
|
|
/// <param name="selectedObject">Object which present hot region</param>
|
|||
|
|
/// <param name="type">AxisName of the object which present hot region</param>
|
|||
|
|
/// <param name="series">Selected series</param>
|
|||
|
|
[
|
|||
|
|
System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "hRef"),
|
|||
|
|
System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "mapAreaAttributes"),
|
|||
|
|
System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "postBackValue"),
|
|||
|
|
System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "toolTip")
|
|||
|
|
]
|
|||
|
|
internal void AddHotRegion( RectangleF rectArea, string toolTip, string hRef, string mapAreaAttributes, string postBackValue, object selectedObject, ChartElementType type, string series )
|
|||
|
|
{
|
|||
|
|
#if !Microsoft_CONTROL
|
|||
|
|
if( ( ProcessChartMode & ProcessMode.ImageMaps ) == ProcessMode.ImageMaps )
|
|||
|
|
{
|
|||
|
|
// Add items to the image map collection
|
|||
|
|
if (_common.ChartPicture.IsMapEnabled == true)
|
|||
|
|
{
|
|||
|
|
if(toolTip.Length > 0 ||
|
|||
|
|
hRef.Length > 0 ||
|
|||
|
|
mapAreaAttributes.Length > 0 ||
|
|||
|
|
postBackValue.Length > 0)
|
|||
|
|
{
|
|||
|
|
MapArea area = new MapArea(
|
|||
|
|
toolTip,
|
|||
|
|
hRef,
|
|||
|
|
mapAreaAttributes,
|
|||
|
|
postBackValue,
|
|||
|
|
rectArea,
|
|||
|
|
((IChartMapArea)selectedObject).Tag);
|
|||
|
|
area.IsCustom = false;
|
|||
|
|
_common.ChartPicture.MapAreas.Add( area);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#endif // !Microsoft_CONTROL
|
|||
|
|
|
|||
|
|
if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
|
|||
|
|
{
|
|||
|
|
HotRegion region = new HotRegion();
|
|||
|
|
|
|||
|
|
region.BoundingRectangle = rectArea;
|
|||
|
|
region.RelativeCoordinates = true;
|
|||
|
|
region.Type = type;
|
|||
|
|
region.SelectedObject = selectedObject;
|
|||
|
|
if(!String.IsNullOrEmpty(series))
|
|||
|
|
{
|
|||
|
|
region.SeriesName = series;
|
|||
|
|
}
|
|||
|
|
_regionList.Add( region );
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Add Hot region to the collection.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="rectArea">Hot Region rectangle</param>
|
|||
|
|
/// <param name="toolTip">Tool Tip Text</param>
|
|||
|
|
/// <param name="hRef">HRef string</param>
|
|||
|
|
/// <param name="mapAreaAttributes">Map area Attribute string</param>
|
|||
|
|
/// <param name="postBackValue">The post back value associated with this item</param>
|
|||
|
|
/// <param name="selectedObject">Object which present hot region</param>
|
|||
|
|
/// <param name="selectedSubObject">Sub-Object which present hot region</param>
|
|||
|
|
/// <param name="type">AxisName of the object which present hot region</param>
|
|||
|
|
/// <param name="series">Selected series</param>
|
|||
|
|
[
|
|||
|
|
System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "hRef"),
|
|||
|
|
System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "mapAreaAttributes"),
|
|||
|
|
System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "postBackValue"),
|
|||
|
|
System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "toolTip")
|
|||
|
|
]
|
|||
|
|
internal void AddHotRegion(
|
|||
|
|
RectangleF rectArea,
|
|||
|
|
string toolTip,
|
|||
|
|
string hRef,
|
|||
|
|
string mapAreaAttributes,
|
|||
|
|
string postBackValue,
|
|||
|
|
object selectedObject,
|
|||
|
|
object selectedSubObject,
|
|||
|
|
ChartElementType type,
|
|||
|
|
string series )
|
|||
|
|
{
|
|||
|
|
#if !Microsoft_CONTROL
|
|||
|
|
if( ( ProcessChartMode & ProcessMode.ImageMaps ) == ProcessMode.ImageMaps )
|
|||
|
|
{
|
|||
|
|
// Add items to the image map collection
|
|||
|
|
if (_common.ChartPicture.IsMapEnabled == true)
|
|||
|
|
{
|
|||
|
|
if(toolTip.Length > 0 ||
|
|||
|
|
hRef.Length > 0 ||
|
|||
|
|
mapAreaAttributes.Length > 0 ||
|
|||
|
|
postBackValue.Length > 0)
|
|||
|
|
{
|
|||
|
|
MapArea area = new MapArea(
|
|||
|
|
toolTip,
|
|||
|
|
hRef,
|
|||
|
|
mapAreaAttributes,
|
|||
|
|
postBackValue,
|
|||
|
|
rectArea,
|
|||
|
|
((IChartMapArea)selectedObject).Tag);
|
|||
|
|
area.IsCustom = false;
|
|||
|
|
_common.ChartPicture.MapAreas.Add( area);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#endif // !Microsoft_CONTROL
|
|||
|
|
|
|||
|
|
if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
|
|||
|
|
{
|
|||
|
|
HotRegion region = new HotRegion();
|
|||
|
|
|
|||
|
|
region.BoundingRectangle = rectArea;
|
|||
|
|
region.RelativeCoordinates = true;
|
|||
|
|
region.Type = type;
|
|||
|
|
region.SelectedObject = selectedObject;
|
|||
|
|
region.SelectedSubObject = selectedSubObject;
|
|||
|
|
if(!String.IsNullOrEmpty(series))
|
|||
|
|
{
|
|||
|
|
region.SeriesName = series;
|
|||
|
|
}
|
|||
|
|
_regionList.Add( region );
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Add Hot region to the collection.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="graph">Chart Graphics Object</param>
|
|||
|
|
/// <param name="path">Graphics path</param>
|
|||
|
|
/// <param name="relativePath">Used relative coordinates for graphics path.</param>
|
|||
|
|
/// <param name="toolTip">Tool Tip Text</param>
|
|||
|
|
/// <param name="hRef">HRef string</param>
|
|||
|
|
/// <param name="mapAreaAttributes">Map area Attribute string</param>
|
|||
|
|
/// <param name="postBackValue">The post back value associated with this item</param>
|
|||
|
|
/// <param name="selectedObject">Object which present hot region</param>
|
|||
|
|
/// <param name="type">AxisName of the object which present hot region</param>
|
|||
|
|
[
|
|||
|
|
System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "graph"),
|
|||
|
|
System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "hRef"),
|
|||
|
|
System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "mapAreaAttributes"),
|
|||
|
|
System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "postBackValue"),
|
|||
|
|
System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "toolTip")
|
|||
|
|
]
|
|||
|
|
internal void AddHotRegion( ChartGraphics graph, GraphicsPath path, bool relativePath, string toolTip, string hRef, string mapAreaAttributes, string postBackValue, object selectedObject, ChartElementType type )
|
|||
|
|
{
|
|||
|
|
#if !Microsoft_CONTROL
|
|||
|
|
if( ( ProcessChartMode & ProcessMode.ImageMaps ) == ProcessMode.ImageMaps )
|
|||
|
|
{
|
|||
|
|
if (_common.ChartPicture.IsMapEnabled == true)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
if(toolTip.Length > 0 ||
|
|||
|
|
hRef.Length > 0 ||
|
|||
|
|
mapAreaAttributes.Length > 0 ||
|
|||
|
|
postBackValue.Length > 0)
|
|||
|
|
{
|
|||
|
|
_common.ChartPicture.MapAreas.InsertPath(
|
|||
|
|
0,
|
|||
|
|
toolTip,
|
|||
|
|
hRef,
|
|||
|
|
mapAreaAttributes,
|
|||
|
|
postBackValue,
|
|||
|
|
path,
|
|||
|
|
!relativePath,
|
|||
|
|
graph
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#endif // !Microsoft_CONTROL
|
|||
|
|
|
|||
|
|
if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
HotRegion region = new HotRegion();
|
|||
|
|
|
|||
|
|
region.Type = type;
|
|||
|
|
region.Path = (GraphicsPath)path.Clone();
|
|||
|
|
region.SelectedObject = selectedObject;
|
|||
|
|
region.BoundingRectangle = path.GetBounds();
|
|||
|
|
region.RelativeCoordinates = relativePath;
|
|||
|
|
|
|||
|
|
_regionList.Add( region );
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Add Hot region to the collection.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="rectArea">Hot Region rectangle</param>
|
|||
|
|
/// <param name="selectedObject">Object which present hot region</param>
|
|||
|
|
/// <param name="type">AxisName of the object which present hot region</param>
|
|||
|
|
/// <param name="relativeCoordinates">Coordinates for rectangle are relative</param>
|
|||
|
|
internal void AddHotRegion( RectangleF rectArea, object selectedObject, ChartElementType type, bool relativeCoordinates )
|
|||
|
|
{
|
|||
|
|
this.AddHotRegion( rectArea, selectedObject, type, relativeCoordinates, false );
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Add Hot region to the collection.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="rectArea">Hot Region rectangle</param>
|
|||
|
|
/// <param name="selectedObject">Object which present hot region</param>
|
|||
|
|
/// <param name="type">AxisName of the object which present hot region</param>
|
|||
|
|
/// <param name="relativeCoordinates">Coordinates for rectangle are relative</param>
|
|||
|
|
/// <param name="insertAtBeginning">Insert the hot region at the beginning of the collection</param>
|
|||
|
|
internal void AddHotRegion( RectangleF rectArea, object selectedObject, ChartElementType type, bool relativeCoordinates, bool insertAtBeginning )
|
|||
|
|
{
|
|||
|
|
if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
|
|||
|
|
{
|
|||
|
|
HotRegion region = new HotRegion();
|
|||
|
|
|
|||
|
|
region.BoundingRectangle = rectArea;
|
|||
|
|
region.RelativeCoordinates = relativeCoordinates;
|
|||
|
|
region.Type = type;
|
|||
|
|
region.SelectedObject = selectedObject;
|
|||
|
|
|
|||
|
|
if( insertAtBeginning )
|
|||
|
|
{
|
|||
|
|
_regionList.Insert( _regionList.Count - 1, region );
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
_regionList.Add( region );
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Add Hot region to the collection.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="path">Graphics path</param>
|
|||
|
|
/// <param name="relativePath">Used relative coordinates for graphics path.</param>
|
|||
|
|
/// <param name="type">Type of the object which present hot region</param>
|
|||
|
|
/// <param name="selectedObject">Object which present hot region</param>
|
|||
|
|
internal void AddHotRegion(
|
|||
|
|
GraphicsPath path,
|
|||
|
|
bool relativePath,
|
|||
|
|
ChartElementType type,
|
|||
|
|
object selectedObject
|
|||
|
|
)
|
|||
|
|
{
|
|||
|
|
if( ( ProcessChartMode & ProcessMode.HotRegions ) == ProcessMode.HotRegions )
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
HotRegion region = new HotRegion();
|
|||
|
|
|
|||
|
|
region.SelectedObject = selectedObject;
|
|||
|
|
region.Type = type;
|
|||
|
|
region.Path = (GraphicsPath)path.Clone();
|
|||
|
|
region.BoundingRectangle = path.GetBounds();
|
|||
|
|
region.RelativeCoordinates = relativePath;
|
|||
|
|
|
|||
|
|
_regionList.Add( region );
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// This method search for position in Map Areas which is the first
|
|||
|
|
/// position after Custom areas.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns>Insert Index</returns>
|
|||
|
|
internal int FindInsertIndex()
|
|||
|
|
{
|
|||
|
|
int insertIndex = 0;
|
|||
|
|
#if !Microsoft_CONTROL
|
|||
|
|
foreach (MapArea mapArea in _common.ChartPicture.MapAreas)
|
|||
|
|
{
|
|||
|
|
if(!mapArea.IsCustom)
|
|||
|
|
{
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
++insertIndex;
|
|||
|
|
}
|
|||
|
|
#endif // !Microsoft_CONTROL
|
|||
|
|
|
|||
|
|
return insertIndex;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Clears this instance.
|
|||
|
|
/// </summary>
|
|||
|
|
public void Clear()
|
|||
|
|
{
|
|||
|
|
foreach (HotRegion hotRegion in this._regionList)
|
|||
|
|
hotRegion.Dispose();
|
|||
|
|
|
|||
|
|
this._regionList.Clear();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion // Methods
|
|||
|
|
|
|||
|
|
#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 virtual void Dispose(bool disposing)
|
|||
|
|
{
|
|||
|
|
if (disposing)
|
|||
|
|
{
|
|||
|
|
if (this._regionList != null)
|
|||
|
|
{
|
|||
|
|
foreach (HotRegion hotRegion in this._regionList)
|
|||
|
|
hotRegion.Dispose();
|
|||
|
|
|
|||
|
|
this._regionList.Clear();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
|||
|
|
/// </summary>
|
|||
|
|
public void Dispose()
|
|||
|
|
{
|
|||
|
|
Dispose(true);
|
|||
|
|
GC.SuppressFinalize(this);
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// The HitTestResult class contains the result of the hit test function.
|
|||
|
|
/// </summary>
|
|||
|
|
#if ASPPERM_35
|
|||
|
|
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
|
|||
|
|
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
|
|||
|
|
#endif
|
|||
|
|
public class HitTestResult
|
|||
|
|
{
|
|||
|
|
#region Fields
|
|||
|
|
|
|||
|
|
// Private members
|
|||
|
|
private object _obj = null;
|
|||
|
|
private Series _series = null;
|
|||
|
|
private int _dataPoint = -1;
|
|||
|
|
private ChartArea _chartArea = null;
|
|||
|
|
private Axis _axis = null;
|
|||
|
|
private ChartElementType _type = ChartElementType.Nothing;
|
|||
|
|
private object _subObject = null;
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region Properties
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets or sets the data series object.
|
|||
|
|
/// </summary>
|
|||
|
|
public Series Series
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _series;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_series = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets or sets the data point index.
|
|||
|
|
/// </summary>
|
|||
|
|
public int PointIndex
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _dataPoint;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_dataPoint = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets or sets the chart area object.
|
|||
|
|
/// </summary>
|
|||
|
|
public ChartArea ChartArea
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _chartArea;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_chartArea = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets or sets the axis object.
|
|||
|
|
/// </summary>
|
|||
|
|
public Axis Axis
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _axis;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_axis = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets or sets the chart element type.
|
|||
|
|
/// </summary>
|
|||
|
|
public ChartElementType ChartElementType
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _type;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_type = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets or sets the selected object.
|
|||
|
|
/// </summary>
|
|||
|
|
public object Object
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _obj;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_obj = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets or sets the selected sub object.
|
|||
|
|
/// </summary>
|
|||
|
|
public object SubObject
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _subObject;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_subObject = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// This class represents an array of marker points and
|
|||
|
|
/// the outline path used for visual object selection in the chart.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <remarks>
|
|||
|
|
/// <see cref="OutlinePath"/> may be null for complex objects or objects with two points or fewer.
|
|||
|
|
/// </remarks>
|
|||
|
|
#if ASPPERM_35
|
|||
|
|
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
|
|||
|
|
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
|
|||
|
|
#endif
|
|||
|
|
public class ChartElementOutline : IDisposable
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// Initializes a new instance of the <see cref="ChartElementOutline"/> class.
|
|||
|
|
/// </summary>
|
|||
|
|
internal ChartElementOutline()
|
|||
|
|
{
|
|||
|
|
this.Markers = new ReadOnlyCollection<PointF>( new PointF[] {});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the markers.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <value>The markers.</value>
|
|||
|
|
public ReadOnlyCollection<PointF> Markers { get; internal set; }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets or sets the outline path. The result could be null for complex objects and objects with two points or fewer.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <value>The outline path.</value>
|
|||
|
|
public GraphicsPath OutlinePath { get; internal set; }
|
|||
|
|
|
|||
|
|
|
|||
|
|
#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 virtual void Dispose(bool disposing)
|
|||
|
|
{
|
|||
|
|
if (disposing)
|
|||
|
|
{
|
|||
|
|
if (this.OutlinePath != null)
|
|||
|
|
{
|
|||
|
|
this.OutlinePath.Dispose();
|
|||
|
|
this.OutlinePath = null;
|
|||
|
|
}
|
|||
|
|
this.Markers = null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
|||
|
|
/// </summary>
|
|||
|
|
[SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
|
|||
|
|
public void Dispose()
|
|||
|
|
{
|
|||
|
|
Dispose(true);
|
|||
|
|
GC.SuppressFinalize(this);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// This class contains methods used for Windows Forms selection.
|
|||
|
|
/// </summary>
|
|||
|
|
internal class Selection : IServiceProvider
|
|||
|
|
#if Microsoft_CONTROL
|
|||
|
|
, IDisposable
|
|||
|
|
#endif //Microsoft_CONTROL
|
|||
|
|
{
|
|||
|
|
#region Fields
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// The chart service container
|
|||
|
|
/// </summary>
|
|||
|
|
private IServiceContainer _service = null;
|
|||
|
|
|
|||
|
|
#if Microsoft_CONTROL
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Stores the tooltip of the control.
|
|||
|
|
/// </summary>
|
|||
|
|
private ToolTip _toolTip = new ToolTip();
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Used by the tooltip - stores the time when the tooltip is activated.
|
|||
|
|
/// </summary>
|
|||
|
|
private DateTime _toolTipActivationTime = DateTime.Now;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Stores the last mouse move X and Y coordinates, so we can ignore false calls to
|
|||
|
|
/// OnMouseMove generated my the tooltip.
|
|||
|
|
/// </summary>
|
|||
|
|
private Point _lastMouseMove = new Point(int.MinValue, int.MinValue);
|
|||
|
|
|
|||
|
|
|
|||
|
|
// ToolTips enabled or disabled from series or legend
|
|||
|
|
private bool _toolTipsEnabled = false;
|
|||
|
|
|
|||
|
|
// Tool tips enabled flag checked
|
|||
|
|
internal bool enabledChecked = false;
|
|||
|
|
|
|||
|
|
#endif //Microsoft_CONTROL
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region Constructors
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Initializes a new instance of the <see cref="Selection"/> class.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="service">The service.</param>
|
|||
|
|
internal Selection(IServiceContainer service)
|
|||
|
|
{
|
|||
|
|
this._service = service;
|
|||
|
|
this._chartControl = this.ChartControl;
|
|||
|
|
#if Microsoft_CONTROL
|
|||
|
|
|
|||
|
|
// Set up the tooltip
|
|||
|
|
this._toolTip.Active = true;
|
|||
|
|
this._toolTip.AutoPopDelay = 30000; // maximum delay possible
|
|||
|
|
this._toolTip.InitialDelay = 500;
|
|||
|
|
this._toolTip.ReshowDelay = 50;
|
|||
|
|
this._toolTip.ShowAlways = true;
|
|||
|
|
this._toolTip.Active = false;
|
|||
|
|
#endif //Microsoft_CONTROL
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#if Microsoft_CONTROL
|
|||
|
|
/// <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>
|
|||
|
|
private void Dispose(bool disposing)
|
|||
|
|
{
|
|||
|
|
if (disposing)
|
|||
|
|
{
|
|||
|
|
if (_toolTip != null)
|
|||
|
|
{
|
|||
|
|
_toolTip.Dispose();
|
|||
|
|
_toolTip = null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
|||
|
|
/// </summary>
|
|||
|
|
public void Dispose()
|
|||
|
|
{
|
|||
|
|
Dispose(true);
|
|||
|
|
GC.SuppressFinalize(this);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endif //Microsoft_CONTROL
|
|||
|
|
|
|||
|
|
#endregion //Constructors
|
|||
|
|
|
|||
|
|
#region Properties
|
|||
|
|
|
|||
|
|
private Chart _chartControl = null;
|
|||
|
|
/// <summary>
|
|||
|
|
/// Returns the attached chart control
|
|||
|
|
/// </summary>
|
|||
|
|
internal Chart ChartControl
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
if (this._chartControl == null)
|
|||
|
|
{
|
|||
|
|
if (this.ChartPicture != null)
|
|||
|
|
{
|
|||
|
|
this._chartControl = this.ChartPicture.Chart;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return this._chartControl;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private ChartPicture _chartPicture = null;
|
|||
|
|
/// <summary>
|
|||
|
|
/// Returns the attached ChartPicture
|
|||
|
|
/// </summary>
|
|||
|
|
internal ChartPicture ChartPicture
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
if (this._chartPicture == null)
|
|||
|
|
{
|
|||
|
|
this._chartPicture = ((IServiceProvider)this).GetService(typeof(ChartImage)) as ChartPicture;
|
|||
|
|
if (this._chartPicture == null)
|
|||
|
|
{
|
|||
|
|
this._chartPicture = ((IServiceProvider)this).GetService(typeof(ChartPicture)) as ChartPicture;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return this._chartPicture;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private Data.DataManager _dataManager = null;
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the chart data manager ( for series access )
|
|||
|
|
/// </summary>
|
|||
|
|
internal Data.DataManager DataManager
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
if (this._dataManager == null)
|
|||
|
|
{
|
|||
|
|
this._dataManager = ((IServiceProvider)this).GetService(typeof(Data.DataManager)) as Data.DataManager;
|
|||
|
|
}
|
|||
|
|
return this._dataManager;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the chart ChartGraphics
|
|||
|
|
/// </summary>
|
|||
|
|
internal ChartGraphics Graph
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
if (this.ChartPicture != null)
|
|||
|
|
{
|
|||
|
|
return this.ChartPicture.Common.graph;
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion //Private Properties
|
|||
|
|
|
|||
|
|
#region Methods
|
|||
|
|
|
|||
|
|
#region Tooltips
|
|||
|
|
#if Microsoft_CONTROL
|
|||
|
|
/// <summary>
|
|||
|
|
/// Checks if tooltips are enabled
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns>true if tooltips enabled</returns>
|
|||
|
|
private bool IsToolTipsEnabled()
|
|||
|
|
{
|
|||
|
|
// Enabled checked. Don<6F>t check every time series
|
|||
|
|
// and data points for tooltips.
|
|||
|
|
if( enabledChecked )
|
|||
|
|
{
|
|||
|
|
return _toolTipsEnabled;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
enabledChecked = true;
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Annotations loop
|
|||
|
|
foreach( Annotation annotation in _chartControl.Annotations )
|
|||
|
|
{
|
|||
|
|
// ToolTip empty
|
|||
|
|
if( annotation.ToolTip.Length > 0 )
|
|||
|
|
{
|
|||
|
|
// ToolTips enabled
|
|||
|
|
_toolTipsEnabled = true;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Data series loop
|
|||
|
|
foreach( Series series in _chartControl.Series )
|
|||
|
|
{
|
|||
|
|
// Check series tooltips
|
|||
|
|
if( series.ToolTip.Length > 0 ||
|
|||
|
|
series.LegendToolTip.Length > 0 ||
|
|||
|
|
series.LabelToolTip.Length > 0)
|
|||
|
|
{
|
|||
|
|
// ToolTips enabled
|
|||
|
|
_toolTipsEnabled = true;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Check if custom properties (Pie collected slice) that create tooltips are used
|
|||
|
|
if(series.IsCustomPropertySet(Utilities.CustomPropertyName.CollectedToolTip))
|
|||
|
|
{
|
|||
|
|
// ToolTips enabled
|
|||
|
|
_toolTipsEnabled = true;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Check point tooltips only for "non-Fast" chart types
|
|||
|
|
if( !series.IsFastChartType() )
|
|||
|
|
{
|
|||
|
|
// Data point loop
|
|||
|
|
foreach( DataPoint point in series.Points )
|
|||
|
|
{
|
|||
|
|
// ToolTip empty
|
|||
|
|
if( point.ToolTip.Length > 0 ||
|
|||
|
|
point.LegendToolTip.Length > 0 ||
|
|||
|
|
point.LabelToolTip.Length > 0)
|
|||
|
|
{
|
|||
|
|
// ToolTips enabled
|
|||
|
|
_toolTipsEnabled = true;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Legend items loop
|
|||
|
|
foreach( Legend legend in _chartControl.Legends )
|
|||
|
|
{
|
|||
|
|
// Check custom legend items
|
|||
|
|
foreach( LegendItem legendItem in legend.CustomItems )
|
|||
|
|
{
|
|||
|
|
// ToolTip empty
|
|||
|
|
if( legendItem.ToolTip.Length > 0 )
|
|||
|
|
{
|
|||
|
|
_toolTipsEnabled = true;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Check all custom cells in the legend item
|
|||
|
|
foreach(LegendCell legendCell in legendItem.Cells)
|
|||
|
|
{
|
|||
|
|
if(legendCell.ToolTip.Length > 0)
|
|||
|
|
{
|
|||
|
|
_toolTipsEnabled = true;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Iterate through legend columns
|
|||
|
|
foreach(LegendCellColumn legendColumn in legend.CellColumns)
|
|||
|
|
{
|
|||
|
|
if(legendColumn.ToolTip.Length > 0)
|
|||
|
|
{
|
|||
|
|
_toolTipsEnabled = true;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Title items loop
|
|||
|
|
foreach( Title title in _chartControl.Titles )
|
|||
|
|
{
|
|||
|
|
// ToolTip empty
|
|||
|
|
if( title.ToolTip.Length > 0 )
|
|||
|
|
{
|
|||
|
|
_toolTipsEnabled = true;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Chart areas loop
|
|||
|
|
foreach( ChartArea area in _chartControl.ChartAreas )
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
// Check if chart area is visible
|
|||
|
|
if(area.Visible)
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
// Axis loop
|
|||
|
|
foreach(Axis axis in area.Axes)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
// Check ToolTip
|
|||
|
|
if( axis.ToolTip.Length > 0 )
|
|||
|
|
{
|
|||
|
|
_toolTipsEnabled = true;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Strip lines loop
|
|||
|
|
foreach(StripLine stripLine in axis.StripLines)
|
|||
|
|
{
|
|||
|
|
// Check ToolTip
|
|||
|
|
if( stripLine.ToolTip.Length > 0 )
|
|||
|
|
{
|
|||
|
|
_toolTipsEnabled = true;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// Check custom labels
|
|||
|
|
foreach(CustomLabel customLabel in axis.CustomLabels)
|
|||
|
|
{
|
|||
|
|
if( customLabel.ToolTip.Length > 0 )
|
|||
|
|
{
|
|||
|
|
_toolTipsEnabled = true;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ToolTips disabled
|
|||
|
|
_toolTipsEnabled = false;
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
[SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily",
|
|||
|
|
Justification = "Too large of a code change to justify making this change")]
|
|||
|
|
internal string EvaluateToolTip(System.Windows.Forms.MouseEventArgs e)
|
|||
|
|
{
|
|||
|
|
object obj;
|
|||
|
|
object subObj;
|
|||
|
|
ChartElementType type;
|
|||
|
|
int dataPointIndex;
|
|||
|
|
string seriesName;
|
|||
|
|
string toolTipText = " ";
|
|||
|
|
|
|||
|
|
HitTestResult hitTest = this.HitTest(e.X, e.Y, true);
|
|||
|
|
|
|||
|
|
type = hitTest.ChartElementType;
|
|||
|
|
dataPointIndex = hitTest.PointIndex;
|
|||
|
|
seriesName = hitTest.Series != null ? hitTest.Series.Name : String.Empty;
|
|||
|
|
obj = hitTest.Object;
|
|||
|
|
subObj = hitTest.SubObject;
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Get tooltips from data points
|
|||
|
|
if (type == ChartElementType.DataPoint)
|
|||
|
|
{
|
|||
|
|
if (_chartControl.Series.IndexOf(seriesName) >= 0 &&
|
|||
|
|
dataPointIndex >= 0 &&
|
|||
|
|
dataPointIndex < _chartControl.Series[seriesName].Points.Count)
|
|||
|
|
{
|
|||
|
|
// Take tool tip from data point
|
|||
|
|
toolTipText = _chartControl.Series[seriesName].Points[dataPointIndex].ReplaceKeywords(_chartControl.Series[seriesName].Points[dataPointIndex].ToolTip);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
DataPoint dataPoint = obj as DataPoint;
|
|||
|
|
if (dataPoint != null)
|
|||
|
|
{
|
|||
|
|
// Take tool tip from data point
|
|||
|
|
toolTipText = dataPoint.ReplaceKeywords(dataPoint.ToolTip);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Get tooltips from data points
|
|||
|
|
if (type == ChartElementType.DataPointLabel)
|
|||
|
|
{
|
|||
|
|
if (_chartControl.Series.IndexOf(seriesName) >= 0 &&
|
|||
|
|
dataPointIndex >= 0 &&
|
|||
|
|
dataPointIndex < _chartControl.Series[seriesName].Points.Count)
|
|||
|
|
{
|
|||
|
|
// Take tool tip from data point
|
|||
|
|
toolTipText = _chartControl.Series[seriesName].Points[dataPointIndex].ReplaceKeywords(_chartControl.Series[seriesName].Points[dataPointIndex].LabelToolTip);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Get tooltips from custom label
|
|||
|
|
if (type == ChartElementType.AxisLabels &&
|
|||
|
|
obj is CustomLabel)
|
|||
|
|
{
|
|||
|
|
toolTipText = ((CustomLabel)obj).ToolTip;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Get tooltips from data points
|
|||
|
|
else if (type == ChartElementType.Annotation && obj != null && obj is Annotation)
|
|||
|
|
{
|
|||
|
|
// Take tool tip from data point
|
|||
|
|
toolTipText = ((Annotation)obj).ReplaceKeywords(((Annotation)obj).ToolTip);
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
// Get tooltips from axis
|
|||
|
|
else if (type == ChartElementType.Axis && obj != null && obj is Axis)
|
|||
|
|
{
|
|||
|
|
// Take tool tip from strip line
|
|||
|
|
toolTipText = ((Axis)obj).ToolTip;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Get tooltips from strip lines
|
|||
|
|
else if (type == ChartElementType.StripLines && obj != null && obj is StripLine)
|
|||
|
|
{
|
|||
|
|
// Take tool tip from strip line
|
|||
|
|
toolTipText = ((StripLine)obj).ToolTip;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
// Get tooltips from data points
|
|||
|
|
else if (type == ChartElementType.Title && obj != null && obj is Title)
|
|||
|
|
{
|
|||
|
|
// Take tool tip from data point
|
|||
|
|
toolTipText = ((Title)obj).ToolTip;
|
|||
|
|
|
|||
|
|
} // Get tooltips for legend items
|
|||
|
|
|
|||
|
|
// Get tooltips for legend items
|
|||
|
|
else if (type == ChartElementType.LegendItem)
|
|||
|
|
{
|
|||
|
|
// Take tool tip from legend item
|
|||
|
|
toolTipText = ((LegendItem)obj).ToolTip;
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Check if cell has it's own tooltip
|
|||
|
|
LegendCell legendCell = subObj as LegendCell;
|
|||
|
|
if (legendCell != null && legendCell.ToolTip.Length > 0)
|
|||
|
|
{
|
|||
|
|
toolTipText = legendCell.ToolTip;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Check if series is associated with legend item
|
|||
|
|
if (toolTipText.Length == 0 &&
|
|||
|
|
seriesName.Length > 0 &&
|
|||
|
|
_chartControl.Series.IndexOf(seriesName) >= 0)
|
|||
|
|
{
|
|||
|
|
// Take tool tip from data point
|
|||
|
|
if (dataPointIndex == -1)
|
|||
|
|
{
|
|||
|
|
if (seriesName.Length > 0)
|
|||
|
|
{
|
|||
|
|
// Take tool tip from series
|
|||
|
|
toolTipText = _chartControl.Series[seriesName].ReplaceKeywords(_chartControl.Series[seriesName].LegendToolTip);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
if (dataPointIndex >= 0 &&
|
|||
|
|
dataPointIndex < _chartControl.Series[seriesName].Points.Count)
|
|||
|
|
{
|
|||
|
|
// Take tool tip from data point
|
|||
|
|
toolTipText = _chartControl.Series[seriesName].Points[dataPointIndex].ReplaceKeywords(_chartControl.Series[seriesName].Points[dataPointIndex].LegendToolTip);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Set event arguments
|
|||
|
|
ToolTipEventArgs args = new ToolTipEventArgs(e.X, e.Y, toolTipText, hitTest);
|
|||
|
|
|
|||
|
|
// Event
|
|||
|
|
_chartControl.OnGetToolTipText(args);
|
|||
|
|
|
|||
|
|
return args.Text.Trim();
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Mouse move event handler.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="sender">Sender</param>
|
|||
|
|
/// <param name="e">Arguments</param>
|
|||
|
|
internal void Selection_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
// Ignore false calls to OnMouseMove caused by the tootip control.
|
|||
|
|
if (e.X == this._lastMouseMove.X && e.Y == this._lastMouseMove.Y)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
this._lastMouseMove.X = e.X;
|
|||
|
|
this._lastMouseMove.Y = e.Y;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Event is not active and tooltip properties are nor set.
|
|||
|
|
if (!IsToolTipsEnabled() && !_chartControl.IsToolTipEventUsed())
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
string newToolTipText = this.EvaluateToolTip(e);
|
|||
|
|
|
|||
|
|
if (!String.IsNullOrEmpty(newToolTipText))
|
|||
|
|
{
|
|||
|
|
string oldToolTipText = this._toolTip.GetToolTip(this._chartControl);
|
|||
|
|
TimeSpan timeSpan = DateTime.Now.Subtract(this._toolTipActivationTime);
|
|||
|
|
if (oldToolTipText != newToolTipText || timeSpan.Milliseconds > 600)
|
|||
|
|
{
|
|||
|
|
// Activate the tooltip
|
|||
|
|
this._toolTip.Active = false;
|
|||
|
|
this._toolTip.SetToolTip(this._chartControl, newToolTipText);
|
|||
|
|
this._toolTip.Active = true;
|
|||
|
|
this._toolTipActivationTime = DateTime.Now;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// We do not have a tooltip, so deactivate it
|
|||
|
|
this._toolTip.Active = false;
|
|||
|
|
this._toolTip.SetToolTip(this._chartControl, string.Empty);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endif //Microsoft_CONTROL
|
|||
|
|
|
|||
|
|
#endregion //Tooltips
|
|||
|
|
|
|||
|
|
#region HitTest
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Call this method to determine the chart element,
|
|||
|
|
/// if any, that is located at a point defined by the given X and Y
|
|||
|
|
/// coordinates.
|
|||
|
|
/// <seealso cref="HitTestResult"/></summary>
|
|||
|
|
/// <param name="x">The X coordinate for the point in question.
|
|||
|
|
/// Often obtained from a parameter in an event
|
|||
|
|
/// (e.g. the X parameter value in the MouseDown event).</param>
|
|||
|
|
/// <param name="y">The Y coordinate for the point in question.
|
|||
|
|
/// Often obtained from a parameter in an event
|
|||
|
|
/// (e.g. the Y parameter value in the MouseDown event).</param>
|
|||
|
|
/// <param name="requestedElementTypes">
|
|||
|
|
/// An array of type which specify the types
|
|||
|
|
/// to test for, on order to filter the result. If omitted checking for
|
|||
|
|
/// elementTypes will be ignored and all kind of elementTypes will be
|
|||
|
|
/// valid.
|
|||
|
|
/// </param>
|
|||
|
|
/// <param name="ignoreTransparent">Indicates that transparent
|
|||
|
|
/// elements should be ignored.</param>
|
|||
|
|
/// <returns>
|
|||
|
|
/// A array of <see cref="HitTestResult"/> objects,
|
|||
|
|
/// which provides information concerning the chart element
|
|||
|
|
/// (if any) that is at the specified location. Result contains at least
|
|||
|
|
/// one element, which could be ChartElementType.Nothing.
|
|||
|
|
/// The objects in the result are sorted in from top to bottom of
|
|||
|
|
/// different layers of control. </returns>
|
|||
|
|
/// <remarks>Call this method to determine the gauge element
|
|||
|
|
/// (if any) that is located at a specified point. Often this method is used in
|
|||
|
|
/// some mouse-related event (e.g. MouseDown)
|
|||
|
|
/// to determine what gauge element the end-user clicked on.
|
|||
|
|
/// The X and Y mouse coordinates obtained from the
|
|||
|
|
/// event parameters are then used for the X and Y parameter
|
|||
|
|
/// values of this method call. The returned
|
|||
|
|
/// <see cref="HitTestResult"/> object's properties
|
|||
|
|
/// can then be used to determine what chart element was clicked on,
|
|||
|
|
/// and also provides a reference to the actual object selected (if
|
|||
|
|
/// any).</remarks>
|
|||
|
|
internal HitTestResult[] HitTest(int x, int y, bool ignoreTransparent, params ChartElementType[] requestedElementTypes)
|
|||
|
|
{
|
|||
|
|
List<HitTestResult> result = new List<HitTestResult>();
|
|||
|
|
ArrayList regionList = this.ChartPicture.Common.HotRegionsList.List;
|
|||
|
|
|
|||
|
|
if (regionList.Count == 0)
|
|||
|
|
{
|
|||
|
|
this.ChartPicture.PaintOffScreen();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
string alowedElements = String.Empty;
|
|||
|
|
if (requestedElementTypes.Length > 0)
|
|||
|
|
{
|
|||
|
|
StringBuilder builder = new StringBuilder();
|
|||
|
|
foreach (ChartElementType elementType in requestedElementTypes)
|
|||
|
|
{
|
|||
|
|
builder.Append(elementType.ToString() + ";");
|
|||
|
|
}
|
|||
|
|
alowedElements = builder.ToString();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
float newX;
|
|||
|
|
float newY;
|
|||
|
|
float relativeX;
|
|||
|
|
float relativeY;
|
|||
|
|
RectangleF newMouseRect;
|
|||
|
|
|
|||
|
|
// Find mouse position in relative and absolute coordinates
|
|||
|
|
RectangleF mouseRect = new RectangleF(x - 1, y - 1, 2, 2);
|
|||
|
|
relativeX = this.Graph.GetRelativePoint(new PointF(x, y)).X;
|
|||
|
|
relativeY = this.Graph.GetRelativePoint(new PointF(x, y)).Y;
|
|||
|
|
RectangleF relativeMouseRect = this.Graph.GetRelativeRectangle(mouseRect);
|
|||
|
|
|
|||
|
|
// Try to pass through series object in design time.
|
|||
|
|
// The series ussualy contain autogenerated points with short lifetime - during painting;
|
|||
|
|
// This hit test result will be used in VS2005 desing time click.
|
|||
|
|
for (int index = regionList.Count - 1; index >= 0; index--)
|
|||
|
|
{
|
|||
|
|
HotRegion region = (HotRegion)regionList[index];
|
|||
|
|
|
|||
|
|
// Check if only looking for specific chart element type
|
|||
|
|
if (!String.IsNullOrEmpty(alowedElements) && alowedElements.IndexOf(region.Type.ToString() + ";", StringComparison.Ordinal) == -1)
|
|||
|
|
{
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Change coordinates if relative path is used
|
|||
|
|
if (region.RelativeCoordinates)
|
|||
|
|
{
|
|||
|
|
newX = relativeX;
|
|||
|
|
newY = relativeY;
|
|||
|
|
newMouseRect = relativeMouseRect;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
newX = (float)x;
|
|||
|
|
newY = (float)y;
|
|||
|
|
newMouseRect = mouseRect;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Check if series name and point index are valid
|
|||
|
|
if (region.SeriesName.Length > 0 &&
|
|||
|
|
(this.ChartControl.Series.IndexOf(region.SeriesName) < 0 || region.PointIndex >= this.ChartControl.Series[region.SeriesName].Points.Count)
|
|||
|
|
)
|
|||
|
|
{
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Check if transparent chart elements should be ignored
|
|||
|
|
if (ignoreTransparent && IsElementTransparent(region))
|
|||
|
|
{
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
// Check intersection with bounding rectangle
|
|||
|
|
if (region.BoundingRectangle.IntersectsWith(newMouseRect))
|
|||
|
|
{
|
|||
|
|
bool pointVisible = false;
|
|||
|
|
|
|||
|
|
if (region.Path != null)
|
|||
|
|
{
|
|||
|
|
// If there is more then one graphical path split them and create
|
|||
|
|
// image maps for every graphical path separately.
|
|||
|
|
GraphicsPathIterator iterator = new GraphicsPathIterator(region.Path);
|
|||
|
|
|
|||
|
|
// There is more then one path.
|
|||
|
|
if (iterator.SubpathCount > 1)
|
|||
|
|
{
|
|||
|
|
GraphicsPath subPath = new GraphicsPath();
|
|||
|
|
while (iterator.NextMarker(subPath) > 0 && pointVisible == false)
|
|||
|
|
{
|
|||
|
|
if (subPath.IsVisible(newX, newY))
|
|||
|
|
{
|
|||
|
|
pointVisible = true;
|
|||
|
|
}
|
|||
|
|
subPath.Reset();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// There is only one path
|
|||
|
|
else if (region.Path.IsVisible(newX, newY))
|
|||
|
|
{
|
|||
|
|
pointVisible = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// Point is inside bounding rectangle and path is not specified
|
|||
|
|
pointVisible = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Check if point is inside the hot region
|
|||
|
|
if (pointVisible)
|
|||
|
|
{
|
|||
|
|
HitTestResult hitTestToAdd = this.GetHitTestResult(
|
|||
|
|
region.SeriesName,
|
|||
|
|
region.PointIndex,
|
|||
|
|
region.Type,
|
|||
|
|
region.SelectedObject,
|
|||
|
|
region.SelectedSubObject
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
int elementIndex = result.FindIndex(
|
|||
|
|
delegate(HitTestResult test)
|
|||
|
|
{
|
|||
|
|
if (
|
|||
|
|
(test.ChartElementType == hitTestToAdd.ChartElementType) &&
|
|||
|
|
(test.Object == hitTestToAdd.Object) &&
|
|||
|
|
(test.SubObject == hitTestToAdd.SubObject) &&
|
|||
|
|
(test.Series == hitTestToAdd.Series) &&
|
|||
|
|
(test.PointIndex == hitTestToAdd.PointIndex)
|
|||
|
|
)
|
|||
|
|
{
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
if (elementIndex == -1)
|
|||
|
|
{
|
|||
|
|
result.Add(hitTestToAdd);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (result.Count == 0)
|
|||
|
|
{
|
|||
|
|
result.Add(this.GetHitTestResult(String.Empty, 0, ChartElementType.Nothing, null, null));
|
|||
|
|
}
|
|||
|
|
return result.ToArray();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// This method performs the hit test and returns a HitTestResult objects.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="x">X coordinate</param>
|
|||
|
|
/// <param name="y">Y coordinate</param>
|
|||
|
|
/// <returns>Hit test result object</returns>
|
|||
|
|
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
|
|||
|
|
Justification = "X and Y are cartesian coordinates and well understood")]
|
|||
|
|
internal HitTestResult HitTest(int x, int y)
|
|||
|
|
{
|
|||
|
|
return this.HitTest(x, y, false, new ChartElementType[] {})[0];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// This method performs the hit test and returns a HitTestResult object.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="x">X coordinate</param>
|
|||
|
|
/// <param name="y">Y coordinate</param>
|
|||
|
|
/// <param name="ignoreTransparent">Indicates that transparent elements should be ignored.</param>
|
|||
|
|
/// <returns>Hit test result object</returns>
|
|||
|
|
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
|
|||
|
|
Justification = "X and Y are cartesian coordinates and well understood")]
|
|||
|
|
public HitTestResult HitTest(int x, int y, bool ignoreTransparent)
|
|||
|
|
{
|
|||
|
|
return this.HitTest(x, y, ignoreTransparent, new ChartElementType[] { })[0];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// This method performs the hit test and returns a HitTestResult object.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="x">X coordinate</param>
|
|||
|
|
/// <param name="y">Y coordinate</param>
|
|||
|
|
/// <param name="requestedElement">Only this chart element will be hit tested.</param>
|
|||
|
|
/// <returns>Hit test result object</returns>
|
|||
|
|
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
|
|||
|
|
Justification = "X and Y are cartesian coordinates and well understood")]
|
|||
|
|
public HitTestResult HitTest(int x, int y, ChartElementType requestedElement)
|
|||
|
|
{
|
|||
|
|
return this.HitTest(x, y, false, requestedElement)[0];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Checks if chart element associated with hot region has transparent background.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="region">Element hot region.</param>
|
|||
|
|
/// <returns>True if chart element is transparent.</returns>
|
|||
|
|
private bool IsElementTransparent(HotRegion region)
|
|||
|
|
{
|
|||
|
|
bool isTransparent = false;
|
|||
|
|
|
|||
|
|
if (region.Type == ChartElementType.DataPoint)
|
|||
|
|
{
|
|||
|
|
if (this.ChartControl != null)
|
|||
|
|
{
|
|||
|
|
DataPoint dataPoint = region.SelectedObject as DataPoint;
|
|||
|
|
if (region.SeriesName.Length > 0)
|
|||
|
|
{
|
|||
|
|
dataPoint = this.ChartControl.Series[region.SeriesName].Points[region.PointIndex];
|
|||
|
|
}
|
|||
|
|
if (dataPoint != null && dataPoint.Color == Color.Transparent)
|
|||
|
|
{
|
|||
|
|
isTransparent = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (region.SelectedObject is Axis)
|
|||
|
|
{
|
|||
|
|
if (((Axis)region.SelectedObject).LineColor == Color.Transparent)
|
|||
|
|
{
|
|||
|
|
isTransparent = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (region.SelectedObject is ChartArea)
|
|||
|
|
{
|
|||
|
|
if (((ChartArea)region.SelectedObject).BackColor == Color.Transparent)
|
|||
|
|
{
|
|||
|
|
isTransparent = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (region.SelectedObject is Legend)
|
|||
|
|
{
|
|||
|
|
if (((Legend)region.SelectedObject).BackColor == Color.Transparent)
|
|||
|
|
{
|
|||
|
|
isTransparent = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (region.SelectedObject is Grid)
|
|||
|
|
{
|
|||
|
|
if (((Grid)region.SelectedObject).LineColor == Color.Transparent)
|
|||
|
|
{
|
|||
|
|
isTransparent = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (region.SelectedObject is StripLine)
|
|||
|
|
{
|
|||
|
|
if (((StripLine)region.SelectedObject).BackColor == Color.Transparent)
|
|||
|
|
{
|
|||
|
|
isTransparent = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (region.SelectedObject is TickMark)
|
|||
|
|
{
|
|||
|
|
if (((TickMark)region.SelectedObject).LineColor == Color.Transparent)
|
|||
|
|
{
|
|||
|
|
isTransparent = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (region.SelectedObject is Title)
|
|||
|
|
{
|
|||
|
|
Title title = (Title)region.SelectedObject;
|
|||
|
|
if ((title.Text.Length == 0 || title.ForeColor == Color.Transparent) &&
|
|||
|
|
(title.BackColor == Color.Transparent || title.BackColor.IsEmpty))
|
|||
|
|
{
|
|||
|
|
isTransparent = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return isTransparent;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Returns Hit Test Result object
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="seriesName">Data series Name</param>
|
|||
|
|
/// <param name="pointIndex">Data point index</param>
|
|||
|
|
/// <param name="type">Selected Chart element type</param>
|
|||
|
|
/// <param name="obj">Selected object</param>
|
|||
|
|
/// <param name="subObject">Selected sub object</param>
|
|||
|
|
/// <returns>Hit test result object</returns>
|
|||
|
|
[SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily",
|
|||
|
|
Justification = "Too large of a code change to justify making this change")]
|
|||
|
|
internal HitTestResult GetHitTestResult(
|
|||
|
|
string seriesName,
|
|||
|
|
int pointIndex,
|
|||
|
|
ChartElementType type,
|
|||
|
|
object obj,
|
|||
|
|
object subObject)
|
|||
|
|
{
|
|||
|
|
HitTestResult result = new HitTestResult();
|
|||
|
|
Chart chart = this.ChartControl;
|
|||
|
|
// If data point is selected convert series
|
|||
|
|
// name to series object.
|
|||
|
|
if (seriesName.Length > 0)
|
|||
|
|
{
|
|||
|
|
result.Series = chart.Series[seriesName];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Selected Object
|
|||
|
|
result.Object = obj;
|
|||
|
|
|
|||
|
|
result.SubObject = subObject;
|
|||
|
|
|
|||
|
|
result.PointIndex = pointIndex;
|
|||
|
|
result.ChartElementType = type;
|
|||
|
|
|
|||
|
|
#if Microsoft_CONTROL
|
|||
|
|
AxisScrollBar scrollBar;
|
|||
|
|
#endif // Microsoft_CONTROL
|
|||
|
|
|
|||
|
|
switch (type)
|
|||
|
|
{
|
|||
|
|
case ChartElementType.Axis:
|
|||
|
|
Axis axis = (Axis)obj;
|
|||
|
|
result.Axis = axis;
|
|||
|
|
if (axis != null)
|
|||
|
|
{
|
|||
|
|
result.ChartArea = axis.ChartArea;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case ChartElementType.DataPoint:
|
|||
|
|
{
|
|||
|
|
if (chart.Series.IndexOf(seriesName) >= 0 &&
|
|||
|
|
pointIndex < chart.Series[seriesName].Points.Count)
|
|||
|
|
{
|
|||
|
|
DataPoint dataPoint = chart.Series[seriesName].Points[pointIndex];
|
|||
|
|
result.Axis = null;
|
|||
|
|
result.ChartArea = chart.ChartAreas[dataPoint.series.ChartArea];
|
|||
|
|
result.Object = dataPoint;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
case ChartElementType.DataPointLabel:
|
|||
|
|
{
|
|||
|
|
if (chart.Series.IndexOf(seriesName) >= 0 &&
|
|||
|
|
pointIndex < chart.Series[seriesName].Points.Count)
|
|||
|
|
{
|
|||
|
|
DataPoint dataPoint = chart.Series[seriesName].Points[pointIndex];
|
|||
|
|
result.Axis = null;
|
|||
|
|
result.ChartArea = chart.ChartAreas[dataPoint.series.ChartArea];
|
|||
|
|
result.Object = dataPoint;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
case ChartElementType.Gridlines:
|
|||
|
|
Grid gridLines = (Grid)obj;
|
|||
|
|
result.Axis = gridLines.Axis;
|
|||
|
|
if (gridLines.Axis != null)
|
|||
|
|
{
|
|||
|
|
result.ChartArea = gridLines.Axis.ChartArea;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case ChartElementType.LegendArea:
|
|||
|
|
result.Axis = null;
|
|||
|
|
result.ChartArea = null;
|
|||
|
|
break;
|
|||
|
|
case ChartElementType.LegendItem:
|
|||
|
|
result.PointIndex = ((LegendItem)obj).SeriesPointIndex;
|
|||
|
|
result.Axis = null;
|
|||
|
|
result.ChartArea = null;
|
|||
|
|
break;
|
|||
|
|
case ChartElementType.PlottingArea:
|
|||
|
|
ChartArea area = (ChartArea)obj;
|
|||
|
|
result.Axis = null;
|
|||
|
|
result.ChartArea = area;
|
|||
|
|
break;
|
|||
|
|
case ChartElementType.StripLines:
|
|||
|
|
StripLine stripLines = (StripLine)obj;
|
|||
|
|
result.Axis = stripLines.Axis;
|
|||
|
|
if (stripLines.Axis != null)
|
|||
|
|
{
|
|||
|
|
result.ChartArea = stripLines.Axis.ChartArea;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case ChartElementType.TickMarks:
|
|||
|
|
TickMark tickMarks = (TickMark)obj;
|
|||
|
|
result.Axis = tickMarks.Axis;
|
|||
|
|
if (tickMarks.Axis != null)
|
|||
|
|
{
|
|||
|
|
result.ChartArea = tickMarks.Axis.ChartArea;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case ChartElementType.Title:
|
|||
|
|
result.Axis = null;
|
|||
|
|
result.ChartArea = null;
|
|||
|
|
break;
|
|||
|
|
case ChartElementType.AxisLabels:
|
|||
|
|
if (obj is CustomLabel)
|
|||
|
|
{
|
|||
|
|
CustomLabel label = (CustomLabel)obj;
|
|||
|
|
result.Axis = label.Axis;
|
|||
|
|
result.ChartArea = label.Axis!=null ? label.Axis.ChartArea : null;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case ChartElementType.AxisLabelImage:
|
|||
|
|
if (obj is CustomLabel)
|
|||
|
|
{
|
|||
|
|
CustomLabel label = (CustomLabel)obj;
|
|||
|
|
result.Axis = label.Axis;
|
|||
|
|
result.ChartArea = label.Axis!=null ? label.Axis.ChartArea : null;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case ChartElementType.AxisTitle:
|
|||
|
|
if (obj is Axis)
|
|||
|
|
{
|
|||
|
|
result.Axis = (Axis)obj;
|
|||
|
|
result.ChartArea = result.Axis.ChartArea;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
#if Microsoft_CONTROL
|
|||
|
|
case ChartElementType.ScrollBarLargeDecrement:
|
|||
|
|
scrollBar = (AxisScrollBar)obj;
|
|||
|
|
result.Axis = scrollBar.axis;
|
|||
|
|
if (scrollBar.axis != null)
|
|||
|
|
{
|
|||
|
|
result.ChartArea = scrollBar.axis.ChartArea;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case ChartElementType.ScrollBarLargeIncrement:
|
|||
|
|
scrollBar = (AxisScrollBar)obj;
|
|||
|
|
result.Axis = scrollBar.axis;
|
|||
|
|
if (scrollBar.axis != null)
|
|||
|
|
{
|
|||
|
|
result.ChartArea = scrollBar.axis.ChartArea;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case ChartElementType.ScrollBarSmallDecrement:
|
|||
|
|
scrollBar = (AxisScrollBar)obj;
|
|||
|
|
result.Axis = scrollBar.axis;
|
|||
|
|
if (scrollBar.axis != null)
|
|||
|
|
{
|
|||
|
|
result.ChartArea = scrollBar.axis.ChartArea;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case ChartElementType.ScrollBarSmallIncrement:
|
|||
|
|
scrollBar = (AxisScrollBar)obj;
|
|||
|
|
result.Axis = scrollBar.axis;
|
|||
|
|
if (scrollBar.axis != null)
|
|||
|
|
{
|
|||
|
|
result.ChartArea = scrollBar.axis.ChartArea;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case ChartElementType.ScrollBarThumbTracker:
|
|||
|
|
scrollBar = (AxisScrollBar)obj;
|
|||
|
|
result.Axis = scrollBar.axis;
|
|||
|
|
if (scrollBar.axis != null)
|
|||
|
|
{
|
|||
|
|
result.ChartArea = scrollBar.axis.ChartArea;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
#endif // Microsoft_CONTROL
|
|||
|
|
|
|||
|
|
case ChartElementType.Annotation:
|
|||
|
|
result.Axis = null;
|
|||
|
|
result.ChartArea = null;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion //HitTest
|
|||
|
|
|
|||
|
|
#region Outline
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the chart element outline.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="chartObject">The chart object.</param>
|
|||
|
|
/// <param name="elementType">Type of the element.</param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
internal ChartElementOutline GetChartElementOutline(object chartObject, ChartElementType elementType)
|
|||
|
|
{
|
|||
|
|
// Check arguments
|
|||
|
|
if (chartObject == null)
|
|||
|
|
throw new ArgumentNullException("chartObject");
|
|||
|
|
|
|||
|
|
// Get outline
|
|||
|
|
ChartElementOutline result = new ChartElementOutline();
|
|||
|
|
chartObject = this.GetAutoGeneratedObject(chartObject);
|
|||
|
|
ArrayList list = this.GetMarkers(chartObject, elementType);
|
|||
|
|
result.Markers = new ReadOnlyCollection<PointF>((PointF[])list.ToArray(typeof(PointF)));
|
|||
|
|
result.OutlinePath = GetGraphicsPath(list, chartObject, elementType);
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion //Outline
|
|||
|
|
|
|||
|
|
#region Selection
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the graphics path.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="markers">The markers.</param>
|
|||
|
|
/// <param name="chartObject">The chart object.</param>
|
|||
|
|
/// <param name="elementType">Type of the element.</param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
private GraphicsPath GetGraphicsPath(IList markers, object chartObject, ChartElementType elementType)
|
|||
|
|
{
|
|||
|
|
bool chartArea3D = false;
|
|||
|
|
ChartArea chartArea = chartObject as ChartArea;
|
|||
|
|
if (chartArea != null && elementType == ChartElementType.PlottingArea)
|
|||
|
|
{
|
|||
|
|
chartArea3D = IsArea3D(chartArea);
|
|||
|
|
}
|
|||
|
|
if (elementType != ChartElementType.DataPoint &&
|
|||
|
|
elementType != ChartElementType.Gridlines &&
|
|||
|
|
elementType != ChartElementType.StripLines &&
|
|||
|
|
elementType != ChartElementType.TickMarks &&
|
|||
|
|
!chartArea3D
|
|||
|
|
)
|
|||
|
|
{
|
|||
|
|
GraphicsPath path = new GraphicsPath();
|
|||
|
|
PointF[] points = new PointF[markers.Count];
|
|||
|
|
markers.CopyTo(points, 0);
|
|||
|
|
if (points.Length > 3)
|
|||
|
|
{
|
|||
|
|
if (elementType == ChartElementType.DataPointLabel)
|
|||
|
|
{
|
|||
|
|
for (int i = 0; i < points.Length; i += 4)
|
|||
|
|
{
|
|||
|
|
RectangleF rect = RectangleF.FromLTRB(points[i].X, points[i].Y, points[i + 2].X, points[i + 2].Y);
|
|||
|
|
path.Reset();
|
|||
|
|
path.AddRectangle(Rectangle.Round(rect));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
if (points.Length == 4)
|
|||
|
|
{
|
|||
|
|
Point[] pointsAlligned = new Point[points.Length];
|
|||
|
|
for (int i = 0; i < points.Length; i++)
|
|||
|
|
{
|
|||
|
|
pointsAlligned[i] = Point.Round(points[i]);
|
|||
|
|
}
|
|||
|
|
path.AddPolygon(pointsAlligned);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
path.AddPolygon(points);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return path;
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static Int32 GetDataPointIndex(DataPoint dataPoint)
|
|||
|
|
{
|
|||
|
|
int pointIndex = -1;
|
|||
|
|
if (dataPoint != null && dataPoint.series != null)
|
|||
|
|
{
|
|||
|
|
pointIndex = dataPoint.series.Points.IndexOf(dataPoint);
|
|||
|
|
if (pointIndex == -1 && dataPoint.IsCustomPropertySet("OriginalPointIndex"))
|
|||
|
|
{
|
|||
|
|
if (!Int32.TryParse(dataPoint.GetCustomProperty("OriginalPointIndex"), out pointIndex))
|
|||
|
|
return -1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return pointIndex;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the auto generated object.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="chartObject">The chart object.</param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
private object GetAutoGeneratedObject(object chartObject)
|
|||
|
|
{
|
|||
|
|
DataPoint dataPoint = chartObject as DataPoint;
|
|||
|
|
if (dataPoint != null)
|
|||
|
|
{
|
|||
|
|
if (dataPoint.series != null)
|
|||
|
|
{
|
|||
|
|
string seriesName = dataPoint.series.Name;
|
|||
|
|
int pointIndex = dataPoint.series.Points.IndexOf(dataPoint);
|
|||
|
|
if (this.ChartControl.Series.IndexOf(seriesName) != -1)
|
|||
|
|
{
|
|||
|
|
Series series = this.ChartControl.Series[seriesName];
|
|||
|
|
if (series.Points.Contains(dataPoint))
|
|||
|
|
{
|
|||
|
|
return chartObject;
|
|||
|
|
}
|
|||
|
|
if (pointIndex >= 0)
|
|||
|
|
{
|
|||
|
|
if (series.Points.Count > pointIndex)
|
|||
|
|
{
|
|||
|
|
return series.Points[pointIndex];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Series asSeries = chartObject as Series;
|
|||
|
|
if (asSeries != null)
|
|||
|
|
{
|
|||
|
|
if (this.ChartControl.Series.Contains(asSeries))
|
|||
|
|
{
|
|||
|
|
return chartObject;
|
|||
|
|
}
|
|||
|
|
if (this.ChartControl.Series.IndexOf(asSeries.Name) != -1)
|
|||
|
|
{
|
|||
|
|
return this.ChartControl.Series[asSeries.Name];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return chartObject;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the hot regions.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="cntxObj">The CNTX obj.</param>
|
|||
|
|
/// <param name="elementType">Type of the element.</param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
private HotRegion[] GetHotRegions(object cntxObj, ChartElementType elementType)
|
|||
|
|
{
|
|||
|
|
ArrayList result = new ArrayList();
|
|||
|
|
HotRegionsList hrList = this.ChartPicture.Common.HotRegionsList;
|
|||
|
|
string dataPointSeries = String.Empty;
|
|||
|
|
int dataPointIndex = -1;
|
|||
|
|
|
|||
|
|
for (int i = hrList.List.Count - 1; i >= 0; i--)
|
|||
|
|
{
|
|||
|
|
HotRegion rgn = (HotRegion)hrList.List[i];
|
|||
|
|
if (rgn.Type == elementType)
|
|||
|
|
{
|
|||
|
|
switch (rgn.Type)
|
|||
|
|
{
|
|||
|
|
case ChartElementType.LegendItem:
|
|||
|
|
LegendItem legendItem = cntxObj as LegendItem;
|
|||
|
|
if (legendItem != null)
|
|||
|
|
{
|
|||
|
|
if (((LegendItem)rgn.SelectedObject).Name == legendItem.Name)
|
|||
|
|
{
|
|||
|
|
result.Add(rgn);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case ChartElementType.AxisLabelImage:
|
|||
|
|
case ChartElementType.AxisLabels:
|
|||
|
|
CustomLabel label1 = cntxObj as CustomLabel;
|
|||
|
|
CustomLabel label2 = rgn.SelectedObject as CustomLabel;
|
|||
|
|
if (label1 != null)
|
|||
|
|
{
|
|||
|
|
if (label1 != null && label2 != null)
|
|||
|
|
{
|
|||
|
|
if (label1.Axis == label2.Axis)
|
|||
|
|
{
|
|||
|
|
if (label1.FromPosition == label2.FromPosition &&
|
|||
|
|
label1.ToPosition == label2.ToPosition &&
|
|||
|
|
label1.RowIndex == label2.RowIndex)
|
|||
|
|
{
|
|||
|
|
if (rgn.Path == null)
|
|||
|
|
{
|
|||
|
|
result.Add(rgn);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Axis axis = cntxObj as Axis;
|
|||
|
|
if (axis != null)
|
|||
|
|
{
|
|||
|
|
if (axis == label2.Axis)
|
|||
|
|
{
|
|||
|
|
if (rgn.Path == null)
|
|||
|
|
{
|
|||
|
|
result.Add(rgn);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case ChartElementType.DataPointLabel:
|
|||
|
|
case ChartElementType.DataPoint:
|
|||
|
|
DataPoint dataPoint = cntxObj as DataPoint;
|
|||
|
|
if (dataPoint != null)
|
|||
|
|
{
|
|||
|
|
if (String.IsNullOrEmpty(dataPointSeries) || dataPointIndex == -1)
|
|||
|
|
{
|
|||
|
|
dataPointSeries = dataPoint.series.Name;
|
|||
|
|
dataPointIndex = GetDataPointIndex(dataPoint);
|
|||
|
|
}
|
|||
|
|
if (rgn.PointIndex == dataPointIndex && rgn.SeriesName == dataPointSeries)
|
|||
|
|
{
|
|||
|
|
result.Add(rgn);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
DataPointCollection dataPointCollection = cntxObj as DataPointCollection;
|
|||
|
|
if (dataPointCollection != null)
|
|||
|
|
{
|
|||
|
|
cntxObj = dataPointCollection.series;
|
|||
|
|
}
|
|||
|
|
Series series = cntxObj as Series;
|
|||
|
|
if (series != null)
|
|||
|
|
{
|
|||
|
|
if (String.IsNullOrEmpty(dataPointSeries) || dataPointIndex == -1)
|
|||
|
|
{
|
|||
|
|
dataPointSeries = series.Name;
|
|||
|
|
}
|
|||
|
|
if (rgn.SeriesName == dataPointSeries)
|
|||
|
|
{
|
|||
|
|
result.Add(rgn);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
default:
|
|||
|
|
if (rgn.SelectedObject == cntxObj)
|
|||
|
|
{
|
|||
|
|
result.Add(rgn);
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return (HotRegion[])result.ToArray(typeof(HotRegion));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the markers from regions.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="chartObject">The chart object.</param>
|
|||
|
|
/// <param name="elementType">Type of the element.</param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
|
|||
|
|
private ArrayList GetMarkersFromRegions(object chartObject, ChartElementType elementType)
|
|||
|
|
{
|
|||
|
|
ArrayList list = new ArrayList();
|
|||
|
|
HotRegion[] regions = this.GetHotRegions(chartObject, elementType);
|
|||
|
|
ChartGraphics graph = this.Graph;
|
|||
|
|
RectangleF rect;
|
|||
|
|
|
|||
|
|
Grid grid = chartObject as Grid;
|
|||
|
|
if (grid != null)
|
|||
|
|
{
|
|||
|
|
foreach (HotRegion rgn in regions)
|
|||
|
|
{
|
|||
|
|
if (!IsArea3D(grid.Axis.ChartArea))
|
|||
|
|
{
|
|||
|
|
if (IsChartAreaCircular(grid.Axis.ChartArea))
|
|||
|
|
{
|
|||
|
|
GraphicsPathIterator iterator = new GraphicsPathIterator(rgn.Path);
|
|||
|
|
|
|||
|
|
// There is more then one path.
|
|||
|
|
if (iterator.SubpathCount > 1)
|
|||
|
|
{
|
|||
|
|
GraphicsPath subPath = new GraphicsPath();
|
|||
|
|
while (iterator.NextMarker(subPath) > 0)
|
|||
|
|
{
|
|||
|
|
rect = subPath.GetBounds();
|
|||
|
|
list.Add(new PointF(rect.Left + rect.Width / 2, rect.Top));
|
|||
|
|
list.Add(new PointF(rect.Right, rect.Top + rect.Height / 2));
|
|||
|
|
list.Add(new PointF(rect.Right - rect.Width / 2, rect.Bottom));
|
|||
|
|
list.Add(new PointF(rect.Left, rect.Bottom - rect.Height / 2));
|
|||
|
|
subPath.Reset();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// 2D
|
|||
|
|
rect = this.GetHotRegionRectangle(rgn, RectangleF.Empty, elementType);
|
|||
|
|
if (grid != null)
|
|||
|
|
{
|
|||
|
|
if (grid.GetAxis().AxisPosition == AxisPosition.Bottom ||
|
|||
|
|
grid.GetAxis().AxisPosition == AxisPosition.Top)
|
|||
|
|
{
|
|||
|
|
rect.Offset(rect.Width / 2, 0);
|
|||
|
|
rect.Width = 0;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
rect.Offset(0, rect.Height / 2);
|
|||
|
|
rect.Height = 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
list.AddRange(this.GetMarkers(rect, false));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{ // 3D
|
|||
|
|
PointF[] points = rgn.Path.PathPoints;
|
|||
|
|
for (int i = 0; i < points.Length - 3; i = i + 4)
|
|||
|
|
{ //Each gridline has a corresponding set of 4 points in the path
|
|||
|
|
//One of the ends of a gridline is in the middle the line between points #0 and #3
|
|||
|
|
//Another ends of a gridline is in the middle the line between points #1 and #2
|
|||
|
|
//So we find those middles and put a marks to the ends of the gridline.
|
|||
|
|
PointF middleP0P3 = new PointF((points[i].X + points[i + 3].X) / 2f, (points[i].Y + points[i + 3].Y) / 2f);
|
|||
|
|
PointF middleP1P2 = new PointF((points[i + 1].X + points[i + 2].X) / 2f, (points[i + 1].Y + points[i + 2].Y) / 2f);
|
|||
|
|
list.Add(graph.GetAbsolutePoint(middleP0P3));
|
|||
|
|
list.Add(graph.GetAbsolutePoint(middleP1P2));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return list;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
DataPoint dataPoint = chartObject as DataPoint;
|
|||
|
|
if (dataPoint != null && elementType != ChartElementType.DataPointLabel)
|
|||
|
|
{
|
|||
|
|
rect = Rectangle.Empty;
|
|||
|
|
Series series = dataPoint.series;
|
|||
|
|
if (this.ChartControl.ChartAreas.IndexOf(series.ChartArea) == -1)
|
|||
|
|
{
|
|||
|
|
return list;
|
|||
|
|
}
|
|||
|
|
ChartArea area = this.ChartControl.ChartAreas[series.ChartArea];
|
|||
|
|
PointF pp = this.Transform3D(area, dataPoint);
|
|||
|
|
if (!(float.IsNaN(pp.X) || float.IsNaN(pp.Y)))
|
|||
|
|
{
|
|||
|
|
list.Add(graph.GetAbsolutePoint(pp));
|
|||
|
|
}
|
|||
|
|
return list;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Axis axis = chartObject as Axis;
|
|||
|
|
if (axis != null && elementType == ChartElementType.AxisTitle)
|
|||
|
|
{
|
|||
|
|
foreach (HotRegion rgn in regions)
|
|||
|
|
{
|
|||
|
|
if (!IsArea3D(axis.ChartArea))
|
|||
|
|
{ // 2D
|
|||
|
|
rect = this.GetHotRegionRectangle(rgn, RectangleF.Empty, elementType);
|
|||
|
|
list.AddRange(this.GetMarkers(rect, elementType));
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{ // 3D
|
|||
|
|
PointF[] points = rgn.Path.PathPoints;
|
|||
|
|
list.AddRange(points);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return list;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
LegendItem legendItem = chartObject as LegendItem;
|
|||
|
|
if (legendItem != null)
|
|||
|
|
{
|
|||
|
|
rect = Rectangle.Empty;
|
|||
|
|
foreach (HotRegion rgn in regions)
|
|||
|
|
{
|
|||
|
|
rect = this.GetHotRegionRectangle(rgn, rect, elementType);
|
|||
|
|
}
|
|||
|
|
if (!rect.IsEmpty)
|
|||
|
|
{
|
|||
|
|
list.AddRange(this.GetMarkers(rect, elementType));
|
|||
|
|
}
|
|||
|
|
return list;
|
|||
|
|
}
|
|||
|
|
else if (chartObject is Annotation)
|
|||
|
|
{
|
|||
|
|
rect = Rectangle.Empty;
|
|||
|
|
foreach (HotRegion rgn in regions)
|
|||
|
|
{
|
|||
|
|
rect = this.GetHotRegionRectangle(rgn, rect, elementType);
|
|||
|
|
}
|
|||
|
|
if (!rect.IsEmpty)
|
|||
|
|
{
|
|||
|
|
list.AddRange(this.GetMarkers(rect, elementType));
|
|||
|
|
}
|
|||
|
|
return list;
|
|||
|
|
}
|
|||
|
|
foreach (HotRegion rgn in regions)
|
|||
|
|
{
|
|||
|
|
rect = this.GetHotRegionRectangle(rgn, RectangleF.Empty, elementType);
|
|||
|
|
list.AddRange(this.GetMarkers(rect, elementType));
|
|||
|
|
}
|
|||
|
|
return list;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the markers.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="chartObject">The chart object.</param>
|
|||
|
|
/// <param name="elementType">Type of the element.</param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
private ArrayList GetMarkers(object chartObject, ChartElementType elementType)
|
|||
|
|
{
|
|||
|
|
ChartArea chartArea = chartObject as ChartArea;
|
|||
|
|
if (chartArea != null)
|
|||
|
|
{
|
|||
|
|
return this.GetAreaMarkers(this.Graph, chartArea);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
Axis axis = chartObject as Axis;
|
|||
|
|
if (axis != null)
|
|||
|
|
{
|
|||
|
|
if (
|
|||
|
|
elementType == ChartElementType.AxisLabelImage ||
|
|||
|
|
elementType == ChartElementType.AxisLabels ||
|
|||
|
|
elementType == ChartElementType.AxisTitle
|
|||
|
|
)
|
|||
|
|
{
|
|||
|
|
return this.GetMarkersFromRegions(chartObject, elementType);
|
|||
|
|
}
|
|||
|
|
return this.GetAxisMarkers(this.Graph, axis);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
DataPoint dataPoint = chartObject as DataPoint;
|
|||
|
|
if (dataPoint != null)
|
|||
|
|
{
|
|||
|
|
return this.GetMarkersFromRegions(chartObject, elementType);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Series series = chartObject as Series;
|
|||
|
|
if (series != null)
|
|||
|
|
{
|
|||
|
|
if (elementType == ChartElementType.DataPointLabel)
|
|||
|
|
{
|
|||
|
|
return this.GetMarkersFromRegions(chartObject, elementType);
|
|||
|
|
}
|
|||
|
|
return this.GetSeriesMarkers(series);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return this.GetMarkersFromRegions(chartObject, elementType);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Determines whether specified chart area is circular or not have axes. These chart areas contain pie, doughnut, polar, radar
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="area">The area.</param>
|
|||
|
|
/// <returns>
|
|||
|
|
/// <c>true</c> if specified chart area is circular; otherwise, <c>false</c>.
|
|||
|
|
/// </returns>
|
|||
|
|
private Boolean IsChartAreaCircular(ChartArea area)
|
|||
|
|
{
|
|||
|
|
foreach (object o in area.ChartTypes)
|
|||
|
|
{
|
|||
|
|
ChartTypes.IChartType chartType = area.Common.ChartTypeRegistry.GetChartType(o.ToString());
|
|||
|
|
if (chartType != null && (chartType.CircularChartArea || !chartType.RequireAxes))
|
|||
|
|
{
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Determines whether the chart area is in 3D mode.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="area">The area.</param>
|
|||
|
|
/// <returns>
|
|||
|
|
/// <c>true</c> if the chart area is in 3D mode; otherwise, <c>false</c>.
|
|||
|
|
/// </returns>
|
|||
|
|
private Boolean IsArea3D(ChartArea area)
|
|||
|
|
{
|
|||
|
|
return area.Area3DStyle.Enable3D && !this.IsChartAreaCircular(area) && area.matrix3D != null && area.matrix3D.IsInitialized();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the series markers.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="series">The series.</param>
|
|||
|
|
/// <returns>List of PointF.</returns>
|
|||
|
|
private ArrayList GetSeriesMarkers(Series series)
|
|||
|
|
{
|
|||
|
|
ArrayList list = new ArrayList();
|
|||
|
|
if (series != null)
|
|||
|
|
{
|
|||
|
|
String areaName = series.ChartArea;
|
|||
|
|
|
|||
|
|
if (String.IsNullOrEmpty(areaName))
|
|||
|
|
{
|
|||
|
|
areaName = ChartPicture.ChartAreas.DefaultNameReference;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (ChartPicture.ChartAreas.IndexOf(areaName) != -1 && series.Enabled)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
ChartArea chartArea = ChartPicture.ChartAreas[areaName];
|
|||
|
|
|
|||
|
|
if (ChartControl.Series.IndexOf(series.Name) != -1)
|
|||
|
|
{
|
|||
|
|
series = ChartControl.Series[series.Name];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
DataPointCollection points = series.Points;
|
|||
|
|
// in design mode we have usually fake points
|
|||
|
|
if (points.Count == 0)
|
|||
|
|
{
|
|||
|
|
points = series.fakeDataPoints;
|
|||
|
|
}
|
|||
|
|
// transform points in 3D
|
|||
|
|
foreach (DataPoint point in points)
|
|||
|
|
{
|
|||
|
|
PointF pp = this.Transform3D(chartArea, point);
|
|||
|
|
if (float.IsNaN(pp.X) || float.IsNaN(pp.Y))
|
|||
|
|
{
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
list.Add(this.Graph.GetAbsolutePoint(pp));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return list;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the axis markers - list of points where markers are drawn.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="graph">The graph.</param>
|
|||
|
|
/// <param name="axis">The axis.</param>
|
|||
|
|
/// <returns>List of PointF.</returns>
|
|||
|
|
private ArrayList GetAxisMarkers(ChartGraphics graph, Axis axis)
|
|||
|
|
{
|
|||
|
|
ArrayList list = new ArrayList();
|
|||
|
|
if (axis == null)
|
|||
|
|
{
|
|||
|
|
return list;
|
|||
|
|
}
|
|||
|
|
PointF first = PointF.Empty;
|
|||
|
|
PointF second = PointF.Empty;
|
|||
|
|
|
|||
|
|
// Set the position of axis
|
|||
|
|
switch (axis.AxisPosition)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
case AxisPosition.Left:
|
|||
|
|
|
|||
|
|
first.X = (float)axis.GetAxisPosition();
|
|||
|
|
first.Y = axis.PlotAreaPosition.Y;
|
|||
|
|
second.X = (float)axis.GetAxisPosition();
|
|||
|
|
second.Y = axis.PlotAreaPosition.Bottom;
|
|||
|
|
first.X -= axis.labelSize + axis.markSize;
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case AxisPosition.Right:
|
|||
|
|
|
|||
|
|
first.X = (float)axis.GetAxisPosition();
|
|||
|
|
first.Y = axis.PlotAreaPosition.Y;
|
|||
|
|
second.X = (float)axis.GetAxisPosition();
|
|||
|
|
second.Y = axis.PlotAreaPosition.Bottom;
|
|||
|
|
second.X += axis.labelSize + axis.markSize;
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case AxisPosition.Bottom:
|
|||
|
|
|
|||
|
|
first.X = axis.PlotAreaPosition.X;
|
|||
|
|
first.Y = (float)axis.GetAxisPosition();
|
|||
|
|
second.X = axis.PlotAreaPosition.Right;
|
|||
|
|
second.Y = (float)axis.GetAxisPosition();
|
|||
|
|
second.Y += axis.labelSize + axis.markSize;
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case AxisPosition.Top:
|
|||
|
|
|
|||
|
|
first.X = axis.PlotAreaPosition.X;
|
|||
|
|
first.Y = (float)axis.GetAxisPosition();
|
|||
|
|
second.X = axis.PlotAreaPosition.Right;
|
|||
|
|
second.Y = (float)axis.GetAxisPosition();
|
|||
|
|
first.Y -= axis.labelSize + axis.markSize;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Update axis line position for circular area
|
|||
|
|
if (axis.ChartArea.chartAreaIsCurcular)
|
|||
|
|
{
|
|||
|
|
second.Y = axis.PlotAreaPosition.Y + axis.PlotAreaPosition.Height / 2f;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
RectangleF rect1 = new RectangleF(first.X, first.Y, second.X - first.X, second.Y - first.Y);
|
|||
|
|
|
|||
|
|
SizeF size = graph.GetRelativeSize(new SizeF(3, 3));
|
|||
|
|
if (axis.AxisPosition == AxisPosition.Top || axis.AxisPosition == AxisPosition.Bottom)
|
|||
|
|
{
|
|||
|
|
rect1.Inflate(2, size.Height);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
rect1.Inflate(size.Width, 2);
|
|||
|
|
}
|
|||
|
|
IList list1 = this.GetMarkers(rect1, ChartElementType.Axis);
|
|||
|
|
ChartArea area = axis.ChartArea;
|
|||
|
|
if (this.IsArea3D(area))
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
Boolean axisOnEdge = false;
|
|||
|
|
float zPositon = axis.GetMarksZPosition(out axisOnEdge);
|
|||
|
|
|
|||
|
|
// Transform coordinates
|
|||
|
|
Point3D[] points = new Point3D[list1.Count];
|
|||
|
|
for (int i = 0; i < list1.Count; i++)
|
|||
|
|
{
|
|||
|
|
points[i] = new Point3D(((PointF)list1[i]).X, ((PointF)list1[i]).Y, zPositon);
|
|||
|
|
}
|
|||
|
|
axis.ChartArea.matrix3D.TransformPoints(points);
|
|||
|
|
for (int i = 0; i < list1.Count; i++)
|
|||
|
|
{
|
|||
|
|
list1[i] = points[i].PointF;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
foreach (PointF p in list1)
|
|||
|
|
{
|
|||
|
|
list.Add(graph.GetAbsolutePoint(p));
|
|||
|
|
}
|
|||
|
|
return list;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the area markers.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="graph">The graph.</param>
|
|||
|
|
/// <param name="area">The area.</param>
|
|||
|
|
/// <returns>List of PointF.</returns>
|
|||
|
|
private ArrayList GetAreaMarkers(ChartGraphics graph, ChartArea area)
|
|||
|
|
{
|
|||
|
|
ArrayList list = new ArrayList();
|
|||
|
|
if (area == null)
|
|||
|
|
{
|
|||
|
|
return list;
|
|||
|
|
}
|
|||
|
|
IList list1 = this.GetMarkers(area.PlotAreaPosition.ToRectangleF(), ChartElementType.PlottingArea);
|
|||
|
|
if (this.IsChartAreaCircular(area))
|
|||
|
|
{
|
|||
|
|
list1 = this.GetMarkers(area.lastAreaPosition, ChartElementType.PlottingArea);
|
|||
|
|
}
|
|||
|
|
if (IsArea3D(area))
|
|||
|
|
{
|
|||
|
|
float zPositon = 0; // area.areaSceneDepth;
|
|||
|
|
// Transform coordinates
|
|||
|
|
Point3D[] points = new Point3D[list1.Count];
|
|||
|
|
for (int i = 0; i < list1.Count; i++)
|
|||
|
|
{
|
|||
|
|
points[i] = new Point3D(((PointF)list1[i]).X, ((PointF)list1[i]).Y, zPositon);
|
|||
|
|
}
|
|||
|
|
area.matrix3D.TransformPoints(points);
|
|||
|
|
for (int i = 0; i < list1.Count; i++)
|
|||
|
|
{
|
|||
|
|
list1[i] = points[i].PointF;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
foreach (PointF p in list1)
|
|||
|
|
{
|
|||
|
|
list.Add(graph.GetAbsolutePoint(p));
|
|||
|
|
}
|
|||
|
|
return list;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Builds list of markers (PointF) based on rectangle
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="rect">The rectangle</param>
|
|||
|
|
/// <param name="elementType">The type of chart elements to retrieve.</param>
|
|||
|
|
/// <returns>List of PointF</returns>
|
|||
|
|
private ArrayList GetMarkers(RectangleF rect, ChartElementType elementType)
|
|||
|
|
{
|
|||
|
|
if (elementType.ToString().StartsWith("Legend", StringComparison.Ordinal) || elementType.ToString().StartsWith("Title", StringComparison.Ordinal))
|
|||
|
|
{
|
|||
|
|
rect.Inflate(4f, 4f);
|
|||
|
|
}
|
|||
|
|
if (elementType.ToString().StartsWith("PlottingArea", StringComparison.Ordinal))
|
|||
|
|
{
|
|||
|
|
SizeF relSize = this.Graph.GetRelativeSize(new SizeF(4f, 4f));
|
|||
|
|
rect.Inflate(relSize.Width, relSize.Height);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ((elementType != ChartElementType.Nothing) && (elementType != ChartElementType.PlottingArea))
|
|||
|
|
{
|
|||
|
|
return this.GetMarkers(rect, false);
|
|||
|
|
}
|
|||
|
|
return this.GetMarkers(rect, true);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Builds list of markers (PointF) based on rectangle
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="rect">The rectangle</param>
|
|||
|
|
/// <param name="addAdditionalMarkers">Add additional markers to the rectangle.</param>
|
|||
|
|
/// <returns>List of PointF</returns>
|
|||
|
|
private ArrayList GetMarkers(RectangleF rect, Boolean addAdditionalMarkers)
|
|||
|
|
{
|
|||
|
|
ArrayList list = new ArrayList();
|
|||
|
|
if (!addAdditionalMarkers)
|
|||
|
|
{
|
|||
|
|
if (rect.Width > 0 && rect.Height > 0)
|
|||
|
|
{
|
|||
|
|
list.Add(new PointF(rect.Left, rect.Top));
|
|||
|
|
list.Add(new PointF(rect.Right, rect.Top));
|
|||
|
|
list.Add(new PointF(rect.Right, rect.Bottom));
|
|||
|
|
list.Add(new PointF(rect.Left, rect.Bottom));
|
|||
|
|
}
|
|||
|
|
else if (rect.Width > 0)
|
|||
|
|
{
|
|||
|
|
list.Add(new PointF(rect.Left, rect.Top));
|
|||
|
|
list.Add(new PointF(rect.Right, rect.Top));
|
|||
|
|
}
|
|||
|
|
else if (rect.Height > 0)
|
|||
|
|
{
|
|||
|
|
list.Add(new PointF(rect.Left, rect.Top));
|
|||
|
|
list.Add(new PointF(rect.Left, rect.Bottom));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
if (rect.Width > 0)
|
|||
|
|
{
|
|||
|
|
list.Add(new PointF(rect.Left, rect.Top));
|
|||
|
|
|
|||
|
|
if (rect.Width > 30)
|
|||
|
|
{
|
|||
|
|
list.Add(new PointF(rect.Left + rect.Width / 2, rect.Top));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
list.Add(new PointF(rect.Right, rect.Top));
|
|||
|
|
|
|||
|
|
if (rect.Height > 30)
|
|||
|
|
{
|
|||
|
|
list.Add(new PointF(rect.Right, rect.Top + rect.Height / 2));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
list.Add(new PointF(rect.Right, rect.Bottom));
|
|||
|
|
if (rect.Width > 30)
|
|||
|
|
{
|
|||
|
|
list.Add(new PointF(rect.Left + rect.Width / 2, rect.Bottom));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
list.Add(new PointF(rect.Left, rect.Bottom));
|
|||
|
|
if (rect.Height > 30)
|
|||
|
|
{
|
|||
|
|
list.Add(new PointF(rect.Left, rect.Top + rect.Height / 2));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
else if (rect.Width > 0)
|
|||
|
|
{
|
|||
|
|
list.Add(new PointF(rect.Left, rect.Top));
|
|||
|
|
|
|||
|
|
if (rect.Width > 30)
|
|||
|
|
{
|
|||
|
|
list.Add(new PointF(rect.Left + rect.Width / 2, rect.Top));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
list.Add(new PointF(rect.Right, rect.Top));
|
|||
|
|
}
|
|||
|
|
else if (rect.Height > 0)
|
|||
|
|
{
|
|||
|
|
list.Add(new PointF(rect.Left, rect.Bottom));
|
|||
|
|
if (rect.Height > 30)
|
|||
|
|
{
|
|||
|
|
list.Add(new PointF(rect.Left, rect.Top + rect.Height / 2));
|
|||
|
|
}
|
|||
|
|
list.Add(new PointF(rect.Left, rect.Top));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return list;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the region markers from graphics path.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="path">The path.</param>
|
|||
|
|
/// <returns>List of PointF.</returns>
|
|||
|
|
private ArrayList GetRegionMarkers(GraphicsPath path)
|
|||
|
|
{
|
|||
|
|
return new ArrayList(path.PathPoints);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Calculates a DataPoint of 3D area into PointF to draw.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="chartArea">3D chart area</param>
|
|||
|
|
/// <param name="point">The DataPoint</param>
|
|||
|
|
/// <returns>Calculated PointF</returns>
|
|||
|
|
private PointF Transform3D(ChartArea chartArea, DataPoint point)
|
|||
|
|
{
|
|||
|
|
if (chartArea is ChartArea && IsArea3D(chartArea))
|
|||
|
|
{
|
|||
|
|
// Get anotation Z coordinate (use scene depth or anchored point Z position)
|
|||
|
|
float positionZ = chartArea.areaSceneDepth;
|
|||
|
|
if (point != null && point.series != null)
|
|||
|
|
{
|
|||
|
|
float depth = 0f;
|
|||
|
|
chartArea.GetSeriesZPositionAndDepth(
|
|||
|
|
point.series,
|
|||
|
|
out depth,
|
|||
|
|
out positionZ);
|
|||
|
|
positionZ += depth / 2f;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
PointF pf = point.positionRel;
|
|||
|
|
|
|||
|
|
// Define 3D points of annotation object
|
|||
|
|
Point3D[] annot3DPoints = new Point3D[1];
|
|||
|
|
annot3DPoints[0] = new Point3D(pf.X, pf.Y, positionZ);
|
|||
|
|
|
|||
|
|
// Tranform cube coordinates
|
|||
|
|
chartArea.matrix3D.TransformPoints(annot3DPoints);
|
|||
|
|
|
|||
|
|
return annot3DPoints[0].PointF;
|
|||
|
|
}
|
|||
|
|
return point.positionRel;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the hot region rectangle.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="rgn">The hot region.</param>
|
|||
|
|
/// <param name="unionWith">The rectangle to union with.</param>
|
|||
|
|
/// <param name="elementType">The type of the element.</param>
|
|||
|
|
/// <returns>Returns the rectangle around the hot region.</returns>
|
|||
|
|
private RectangleF GetHotRegionRectangle(HotRegion rgn, RectangleF unionWith, ChartElementType elementType)
|
|||
|
|
{
|
|||
|
|
RectangleF rect;
|
|||
|
|
if (rgn.Path != null)
|
|||
|
|
{
|
|||
|
|
rect = rgn.Path.GetBounds();
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
rect = rgn.BoundingRectangle;
|
|||
|
|
}
|
|||
|
|
if (rgn.RelativeCoordinates)
|
|||
|
|
{
|
|||
|
|
rect = this.Graph.GetAbsoluteRectangle(rect);
|
|||
|
|
}
|
|||
|
|
if (elementType == ChartElementType.AxisLabels)
|
|||
|
|
{
|
|||
|
|
if (rect.Width > rect.Height)
|
|||
|
|
{
|
|||
|
|
rect.Inflate(-5, -2);
|
|||
|
|
}
|
|||
|
|
else if (rect.Width < rect.Height)
|
|||
|
|
{
|
|||
|
|
rect.Inflate(-2, -5);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (!unionWith.IsEmpty)
|
|||
|
|
{
|
|||
|
|
return RectangleF.Union(unionWith, rect);
|
|||
|
|
}
|
|||
|
|
return rect;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion //Selection
|
|||
|
|
|
|||
|
|
#endregion //Tooltips
|
|||
|
|
|
|||
|
|
#region IServiceProvider Members
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the service object of the specified type.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="serviceType">An object that specifies the type of service object to get.</param>
|
|||
|
|
/// <returns>
|
|||
|
|
/// A service object of type <paramref name="serviceType"/>. It returns null
|
|||
|
|
/// if there is no service object of type <paramref name="serviceType"/>.
|
|||
|
|
/// </returns>
|
|||
|
|
object IServiceProvider.GetService(Type serviceType)
|
|||
|
|
{
|
|||
|
|
if (serviceType == typeof(Selection))
|
|||
|
|
{
|
|||
|
|
return this;
|
|||
|
|
}
|
|||
|
|
if (_service != null)
|
|||
|
|
{
|
|||
|
|
return _service.GetService(serviceType);
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
#if Microsoft_CONTROL
|
|||
|
|
/// <summary>
|
|||
|
|
/// The ToolTipEventArgs class stores the tool tips event arguments.
|
|||
|
|
/// </summary>
|
|||
|
|
public class ToolTipEventArgs : EventArgs
|
|||
|
|
{
|
|||
|
|
#region Private fields
|
|||
|
|
|
|||
|
|
// Private fields for properties values storage
|
|||
|
|
private int x = 0;
|
|||
|
|
private int y = 0;
|
|||
|
|
private string text = "";
|
|||
|
|
private HitTestResult result = new HitTestResult();
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region Constructors
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// ToolTipEventArgs constructor. Creates ToolTip event arguments.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="x">X-coordinate of mouse.</param>
|
|||
|
|
/// <param name="y">Y-coordinate of mouse.</param>
|
|||
|
|
/// <param name="text">Tooltip text.</param>
|
|||
|
|
/// <param name="result">Hit test result object.</param>
|
|||
|
|
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
|
|||
|
|
Justification = "X and Y are cartesian coordinates and well understood")]
|
|||
|
|
public ToolTipEventArgs(int x, int y, string text, HitTestResult result)
|
|||
|
|
{
|
|||
|
|
this.x = x;
|
|||
|
|
this.y = y;
|
|||
|
|
this.text = text;
|
|||
|
|
this.result = result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region Properties
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the x-coordinate of the mouse.
|
|||
|
|
/// </summary>
|
|||
|
|
[
|
|||
|
|
SRDescription("DescriptionAttributeToolTipEventArgs_X"),
|
|||
|
|
]
|
|||
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "X")]
|
|||
|
|
public int X
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return x;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the result of the hit test.
|
|||
|
|
/// </summary>
|
|||
|
|
[
|
|||
|
|
SRDescription("DescriptionAttributeToolTipEventArgs_HitTestResult"),
|
|||
|
|
]
|
|||
|
|
public HitTestResult HitTestResult
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the y-coordinate of the mouse.
|
|||
|
|
/// </summary>
|
|||
|
|
[
|
|||
|
|
SRDescription("DescriptionAttributeToolTipEventArgs_Y"),
|
|||
|
|
]
|
|||
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Y")]
|
|||
|
|
public int Y
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return y;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the text of the tooltip.
|
|||
|
|
/// </summary>
|
|||
|
|
[
|
|||
|
|
SRDescription("DescriptionAttributeToolTipEventArgs_Text"),
|
|||
|
|
]
|
|||
|
|
public string Text
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return text;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
text = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endif // #if Microsoft_CONTROL
|
|||
|
|
}
|