1 //-------------------------------------------------------------
2 // <copyright company=’Microsoft Corporation’>
3 // Copyright © Microsoft Corporation. All Rights Reserved.
5 //-------------------------------------------------------------
6 // @owner=alexgor, deliant
7 //=================================================================
10 // Namespace: DataVisualization.Charting
12 // Classes: Selection, HitTestResult, ToolTipEventArgs,
13 // HotRegionElement, Hot Region
15 // Purpose: This file contains methods used for Win Form selection
17 // Reviewed: AG - Oct 21
19 //===================================================================
22 #region Used namespaces
26 using System
.Drawing
.Drawing2D
;
27 using System
.Collections
;
28 using System
.Collections
.Generic
;
29 using System
.Globalization
;
30 using System
.Diagnostics
.CodeAnalysis
;
31 using System
.ComponentModel
.Design
;
32 using System
.ComponentModel
;
34 using System
.Collections
.ObjectModel
;
37 using System
.Windows
.Forms
;
44 namespace System
.Windows
.Forms
.DataVisualization
.Charting
46 namespace System
.Web
.UI
.DataVisualization
.Charting
52 // Plase keep the folowing enumaration in chart layering order - ex. ChartArea is under DataPoint
54 /// An enumeration of types of Chart Element.
56 public enum ChartElementType
64 /// The title of a chart.
69 /// Plotting area (chart area excluding axes, labels, etc.).
70 /// Also excludes the regions that data points may occupy.
80 /// Any major or minor tick mark.
85 /// Any major or minor grid line (both vertical or horizontal).
90 /// A StripLine object.
110 #if Microsoft_CONTROL
113 /// A scrollbar tracking thumb.
115 ScrollBarThumbTracker
,
118 /// A scrollbar small decrement button. A "down arrow"
119 /// button for a vertical scrollbar, or a "left arrow"
120 /// button for a horizontal scroll bar.
122 ScrollBarSmallDecrement
,
125 /// A scrollbar small increment button. An "up arrow"
126 /// button for a vertical scrollbar, or a "right arrow"
127 /// button for a horizontal scroll bar.
129 ScrollBarSmallIncrement
,
132 /// The background of a scrollbar that will result in
133 /// a large decrement in the scale view size when clicked.
134 /// This is the background below the thumb for
135 /// a vertical scrollbar, and to the left of
136 /// the thumb for a horizontal scrollbar.
138 ScrollBarLargeDecrement
,
141 /// The background of a scrollbar that will result in
142 /// a large increment in the scale view size when clicked.
143 /// This is the background above the thumb for
144 /// a vertical scrollbar, and to the right of
145 /// the thumb for a horizontal scrollbar.
147 ScrollBarLargeIncrement
,
150 /// The zoom reset button of a scrollbar.
154 #endif // Microsoft_CONTROL
157 /// A DataPoint object.
162 /// Series data point label.
167 /// The area inside a Legend object. Does not include
168 /// the space occupied by legend items.
183 /// A LegendItem object.
189 /// Chart annotation object.
197 /// Enumeration (Flag) used for processing chart types.
200 internal enum ProcessMode
208 /// Selection mode. Collection of hot regions has to be created.
213 /// Used for image maps
221 /// This class presents item in
222 /// the collection of hot regions.
224 internal class HotRegion
: IDisposable
228 // Private data members, which store properties values
229 private GraphicsPath _path
= null;
230 private bool _relativeCoordinates
= true;
231 private RectangleF _boundingRectangle
= RectangleF
.Empty
;
232 private object _selectedObject
= null;
233 private int _pointIndex
= -1;
234 private string _seriesName
= "";
235 private ChartElementType _type
= ChartElementType
.Nothing
;
238 private object _selectedSubObject
= null;
246 /// Region is Graphics path
248 internal GraphicsPath Path
261 /// Relative coordinates are used
264 internal bool RelativeCoordinates
268 return _relativeCoordinates
;
272 _relativeCoordinates
= value;
277 /// Bounding Rectangle of an shape
279 internal RectangleF BoundingRectangle
283 return _boundingRectangle
;
287 _boundingRectangle
= value;
292 /// Object which is presented with this region
294 internal object SelectedObject
298 return _selectedObject
;
302 _selectedObject
= value;
309 /// Sub-Object which is presented with this region
311 internal object SelectedSubObject
315 return _selectedSubObject
;
319 _selectedSubObject
= value;
326 /// Index of the data point which is presented with this region
328 internal int PointIndex
341 /// Name of the series which is presented with the region
343 internal string SeriesName
356 /// Chart Element AxisName
358 internal ChartElementType Type
370 #endregion // Properties
372 #region IDisposable members
374 /// Releases unmanaged and - optionally - managed resources
376 /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
377 protected virtual void Dispose(bool disposing
)
390 /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
392 public void Dispose()
395 GC
.SuppressFinalize(this);
402 /// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
405 /// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
407 public override string ToString()
409 string objectType
= this.SelectedObject
!= null ? this.SelectedObject
.ToString() : "null";
410 if (this.SelectedObject
== null && !String
.IsNullOrEmpty(this.SeriesName
))
412 objectType
= this.SeriesName
;
414 return String
.Format(CultureInfo
.CurrentCulture
, "{0} of {1}", this.Type
, objectType
);
421 /// This class is used to fill and
422 /// manage collection with Hot Regions
424 internal class HotRegionsList
: IDisposable
429 /// Process chart mode Flag
431 private ProcessMode _processChartMode
= ProcessMode
.Paint
;
434 /// Collection with Hor Region Elements
436 private System
.Collections
.ArrayList _regionList
= new ArrayList();
439 /// Reference to the common elements object
441 private CommonElements _common
= null;
443 #if Microsoft_CONTROL
446 /// True if hit test function is called
448 internal bool hitTestCalled
= false;
450 #endif // Microsoft_CONTROL
457 /// Flag used for processing chart types. It could
458 /// be Paint, HotRegion or both mode.
460 internal ProcessMode ProcessChartMode
464 return _processChartMode
;
468 _processChartMode
= value;
469 if(this._common
!= null)
471 this._common
.processModePaint
=
472 (_processChartMode
& ProcessMode
.Paint
) == ProcessMode
.Paint
;
473 this._common
.processModeRegions
=
474 ( _processChartMode
& ProcessMode
.HotRegions
) == ProcessMode
.HotRegions
||
475 ( _processChartMode
& ProcessMode
.ImageMaps
) == ProcessMode
.ImageMaps
;
481 /// Collection with Hor Region Elements
483 internal ArrayList List
491 #endregion // Properties
498 /// <param name="common">Reference to the CommonElements</param>
499 internal HotRegionsList( CommonElements common
)
501 this._common
= common
;
505 /// Add hot region to the collection.
507 /// <param name="rectSize">Rectangle which presents an Hot Region</param>
508 /// <param name="point">Data Point</param>
509 /// <param name="seriesName">Data Series</param>
510 /// <param name="pointIndex">Index of an Data Point in the series</param>
511 [System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
512 public void AddHotRegion(
520 #if !Microsoft_CONTROL
521 if( ( ProcessChartMode
& ProcessMode
.ImageMaps
) == ProcessMode
.ImageMaps
)
523 if (_common
.ChartPicture
.IsMapEnabled
== true)
525 if(point
.ToolTip
.Length
> 0 ||
526 point
.Url
.Length
> 0 ||
527 point
.MapAreaAttributes
.Length
> 0 ||
528 point
.PostBackValue
.Length
> 0
531 MapArea area
= new MapArea(
532 point
.ReplaceKeywords(point
.ToolTip
),
533 point
.ReplaceKeywords(point
.Url
),
534 point
.ReplaceKeywords(point
.MapAreaAttributes
),
535 point
.ReplaceKeywords(point
.PostBackValue
),
538 area
.IsCustom
= false;
539 _common
.ChartPicture
.MapAreas
.Insert(0, area
);
543 #endif // !Microsoft_CONTROL
545 if( ( ProcessChartMode
& ProcessMode
.HotRegions
) == ProcessMode
.HotRegions
)
547 HotRegion region
= new HotRegion();
549 region
.BoundingRectangle
= rectSize
;
550 region
.SeriesName
= seriesName
;
551 region
.PointIndex
= pointIndex
;
552 region
.Type
= ChartElementType
.DataPoint
;
553 region
.RelativeCoordinates
= true;
557 // Use index of the original data point
558 if(point
!= null && point
.IsCustomPropertySet("OriginalPointIndex"))
560 region
.PointIndex
= int.Parse(point
["OriginalPointIndex"], CultureInfo
.InvariantCulture
);
565 _regionList
.Add( region
);
571 /// Adds the hot region.
573 /// <param name="path">Bounding GraphicsPath.</param>
574 /// <param name="relativePath">if set to <c>true</c> the is relative path.</param>
575 /// <param name="graph">Chart Graphics Object</param>
576 /// <param name="point">Selected data point</param>
577 /// <param name="seriesName">Name of the series.</param>
578 /// <param name="pointIndex">Index of the point.</param>
579 [System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId
= "graph")]
580 internal void AddHotRegion(
593 #if !Microsoft_CONTROL
594 if( ( ProcessChartMode
& ProcessMode
.ImageMaps
) == ProcessMode
.ImageMaps
)
596 if (_common
.ChartPicture
.IsMapEnabled
== true)
598 if(point
.ToolTip
.Length
> 0 ||
599 point
.Url
.Length
> 0 ||
600 point
.MapAreaAttributes
.Length
> 0 ||
601 point
.PostBackValue
.Length
> 0
604 int prevMapAreaCount
= _common
.ChartPicture
.MapAreas
.Count
;
605 _common
.ChartPicture
.MapAreas
.InsertPath(
607 point
.ReplaceKeywords(point
.ToolTip
),
608 point
.ReplaceKeywords(point
.Url
),
609 point
.ReplaceKeywords(point
.MapAreaAttributes
),
610 point
.ReplaceKeywords(point
.PostBackValue
),
618 for (int i
= 0; i
< _common
.ChartPicture
.MapAreas
.Count
- prevMapAreaCount
; i
++)
619 ((IChartMapArea
)_common
.ChartPicture
.MapAreas
[i
]).Tag
= ((IChartMapArea
)point
).Tag
;
623 #endif // !Microsoft_CONTROL
625 if( ( ProcessChartMode
& ProcessMode
.HotRegions
) == ProcessMode
.HotRegions
)
628 HotRegion region
= new HotRegion();
630 region
.SeriesName
= seriesName
;
631 region
.PointIndex
= pointIndex
;
632 region
.Type
= ChartElementType
.DataPoint
;
633 region
.Path
= (GraphicsPath
)path
.Clone();
634 region
.BoundingRectangle
= path
.GetBounds();
635 region
.RelativeCoordinates
= relativePath
;
639 // Use index of the original data point
640 if(point
!= null && point
.IsCustomPropertySet("OriginalPointIndex"))
642 region
.PointIndex
= int.Parse(point
["OriginalPointIndex"], CultureInfo
.InvariantCulture
);
647 _regionList
.Add( region
);
653 /// Adds the hot region.
655 /// <param name="insertIndex">Position where to insert element. Used for image maps only</param>
656 /// <param name="path">Bounding GraphicsPath.</param>
657 /// <param name="relativePath">if set to <c>true</c> the is relative path.</param>
658 /// <param name="graph">Chart Graphics Object</param>
659 /// <param name="point">Selected data point</param>
660 /// <param name="seriesName">Name of the series.</param>
661 /// <param name="pointIndex">Index of the point.</param>
663 System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId
= "graph"),
664 System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId
= "insertIndex")
666 internal void AddHotRegion(
676 #if !Microsoft_CONTROL
677 if( ( ProcessChartMode
& ProcessMode
.ImageMaps
) == ProcessMode
.ImageMaps
)
679 if (_common
.ChartPicture
.IsMapEnabled
== true)
681 if(point
.ToolTip
.Length
> 0 ||
682 point
.Url
.Length
> 0 ||
683 point
.MapAreaAttributes
.Length
> 0 ||
684 point
.PostBackValue
.Length
> 0)
687 int prevMapAreaCount
= _common
.ChartPicture
.MapAreas
.Count
;
689 _common
.ChartPicture
.MapAreas
.InsertPath(
691 point
.ReplaceKeywords(point
.ToolTip
),
692 point
.ReplaceKeywords(point
.Url
),
693 point
.ReplaceKeywords(point
.MapAreaAttributes
),
694 point
.ReplaceKeywords(point
.PostBackValue
),
701 for (int i
= insertIndex
; i
< _common
.ChartPicture
.MapAreas
.Count
- prevMapAreaCount
; i
++)
702 ((IChartMapArea
)_common
.ChartPicture
.MapAreas
[i
]).Tag
= ((IChartMapArea
)point
).Tag
;
706 #endif // !Microsoft_CONTROL
708 if( ( ProcessChartMode
& ProcessMode
.HotRegions
) == ProcessMode
.HotRegions
)
711 HotRegion region
= new HotRegion();
713 region
.SeriesName
= seriesName
;
714 region
.PointIndex
= pointIndex
;
715 region
.Type
= ChartElementType
.DataPoint
;
716 region
.Path
= (GraphicsPath
)path
.Clone();
717 region
.BoundingRectangle
= path
.GetBounds();
718 region
.RelativeCoordinates
= relativePath
;
722 // Use index of the original data point
723 if(point
!= null && point
.IsCustomPropertySet("OriginalPointIndex"))
725 region
.PointIndex
= int.Parse(point
["OriginalPointIndex"], CultureInfo
.InvariantCulture
);
730 _regionList
.Add( region
);
736 /// Add hot region to the collection.
738 /// <param name="path">Graphics path which presents hot region</param>
739 /// <param name="relativePath">Graphics path uses relative or absolute coordinates</param>
740 /// <param name="coord">Coordinates which defines polygon (Graphics Path). Used for image maps</param>
741 /// <param name="point">Selected data point</param>
742 /// <param name="seriesName">Data Series</param>
743 /// <param name="pointIndex">Index of an Data Point in the series</param>
744 [System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId
= "coord")]
745 internal void AddHotRegion( GraphicsPath path
, bool relativePath
, float [] coord
, DataPoint point
, string seriesName
, int pointIndex
)
748 #if !Microsoft_CONTROL
749 if( ( ProcessChartMode
& ProcessMode
.ImageMaps
) == ProcessMode
.ImageMaps
)
751 if (_common
.ChartPicture
.IsMapEnabled
== true)
753 if(point
.ToolTip
.Length
> 0 ||
754 point
.Url
.Length
> 0 ||
755 point
.MapAreaAttributes
.Length
> 0 ||
756 point
.PostBackValue
.Length
> 0)
758 MapArea area
= new MapArea(
759 MapAreaShape
.Polygon
,
760 point
.ReplaceKeywords(point
.ToolTip
),
761 point
.ReplaceKeywords(point
.Url
),
762 point
.ReplaceKeywords(point
.MapAreaAttributes
),
763 point
.ReplaceKeywords(point
.PostBackValue
),
766 area
.IsCustom
= false;
767 _common
.ChartPicture
.MapAreas
.Insert(0,area
);
772 #endif // !Microsoft_CONTROL
774 if( ( ProcessChartMode
& ProcessMode
.HotRegions
) == ProcessMode
.HotRegions
)
777 HotRegion region
= new HotRegion();
779 region
.SeriesName
= seriesName
;
780 region
.PointIndex
= pointIndex
;
781 region
.Type
= ChartElementType
.DataPoint
;
782 region
.Path
= (GraphicsPath
)path
.Clone();
783 region
.BoundingRectangle
= path
.GetBounds();
784 region
.RelativeCoordinates
= relativePath
;
788 // Use index of the original data point
789 if(point
!= null && point
.IsCustomPropertySet("OriginalPointIndex"))
791 region
.PointIndex
= int.Parse(point
["OriginalPointIndex"], CultureInfo
.InvariantCulture
);
796 _regionList
.Add( region
);
803 /// Add Hot region to the collection.
805 /// <param name="insertIndex">Position where to insert element. Used for image maps only</param>
806 /// <param name="graph">Chart Graphics Object</param>
807 /// <param name="x">x coordinate.</param>
808 /// <param name="y">y coordinate.</param>
809 /// <param name="radius">The radius.</param>
810 /// <param name="point">Selected data point</param>
811 /// <param name="seriesName">Data Series</param>
812 /// <param name="pointIndex">Index of an Data Point in the series</param>
813 [System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId
= "insertIndex")]
814 internal void AddHotRegion( int insertIndex
, ChartGraphics graph
, float x
, float y
, float radius
, DataPoint point
, string seriesName
, int pointIndex
)
817 #if !Microsoft_CONTROL
818 if( ( ProcessChartMode
& ProcessMode
.ImageMaps
) == ProcessMode
.ImageMaps
)
820 if (_common
.ChartPicture
.IsMapEnabled
== true)
822 if(point
.ToolTip
.Length
> 0 ||
823 point
.Url
.Length
> 0 ||
824 point
.MapAreaAttributes
.Length
> 0 ||
825 point
.PostBackValue
.Length
> 0 )
828 float[] circCoord
= new float[3];
831 circCoord
[2] = radius
;
833 MapArea area
= new MapArea(
835 point
.ReplaceKeywords(point
.ToolTip
),
836 point
.ReplaceKeywords(point
.Url
),
837 point
.ReplaceKeywords(point
.MapAreaAttributes
),
838 point
.ReplaceKeywords(point
.PostBackValue
),
841 area
.IsCustom
= false;
843 _common
.ChartPicture
.MapAreas
.Insert(insertIndex
,area
);
848 #endif // !Microsoft_CONTROL
850 if( ( ProcessChartMode
& ProcessMode
.HotRegions
) == ProcessMode
.HotRegions
)
852 HotRegion region
= new HotRegion();
854 PointF circleCenter
= graph
.GetAbsolutePoint( new PointF( x
, y
) );
855 SizeF circleRadius
= graph
.GetAbsoluteSize( new SizeF( radius
, radius
) );
857 GraphicsPath path
= new GraphicsPath();
859 circleCenter
.X
- circleRadius
.Width
,
860 circleCenter
.Y
- circleRadius
.Width
,
861 2 * circleRadius
.Width
,
862 2 * circleRadius
.Width
864 region
.BoundingRectangle
= path
.GetBounds();
865 region
.SeriesName
= seriesName
;
866 region
.Type
= ChartElementType
.DataPoint
;
867 region
.PointIndex
= pointIndex
;
869 region
.RelativeCoordinates
= false;
873 // Use index of the original data point
874 if(point
!= null && point
.IsCustomPropertySet("OriginalPointIndex"))
876 region
.PointIndex
= int.Parse(point
["OriginalPointIndex"], CultureInfo
.InvariantCulture
);
881 _regionList
.Add( region
);
887 /// Add Hot region to the collection.
889 /// <param name="rectArea">Hot Region rectangle</param>
890 /// <param name="toolTip">Tool Tip Text</param>
891 /// <param name="hRef">HRef string</param>
892 /// <param name="mapAreaAttributes">Map area Attribute string</param>
893 /// <param name="postBackValue">The post back value associated with this item</param>
894 /// <param name="selectedObject">Object which present hot region</param>
895 /// <param name="type">AxisName of the object which present hot region</param>
896 /// <param name="series">Selected series</param>
898 System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId
= "hRef"),
899 System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId
= "mapAreaAttributes"),
900 System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId
= "postBackValue"),
901 System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId
= "toolTip")
903 internal void AddHotRegion( RectangleF rectArea
, string toolTip
, string hRef
, string mapAreaAttributes
, string postBackValue
, object selectedObject
, ChartElementType type
, string series
)
905 #if !Microsoft_CONTROL
906 if( ( ProcessChartMode
& ProcessMode
.ImageMaps
) == ProcessMode
.ImageMaps
)
908 // Add items to the image map collection
909 if (_common
.ChartPicture
.IsMapEnabled
== true)
911 if(toolTip
.Length
> 0 ||
913 mapAreaAttributes
.Length
> 0 ||
914 postBackValue
.Length
> 0)
916 MapArea area
= new MapArea(
922 ((IChartMapArea
)selectedObject
).Tag
);
923 area
.IsCustom
= false;
924 _common
.ChartPicture
.MapAreas
.Add( area
);
928 #endif // !Microsoft_CONTROL
930 if( ( ProcessChartMode
& ProcessMode
.HotRegions
) == ProcessMode
.HotRegions
)
932 HotRegion region
= new HotRegion();
934 region
.BoundingRectangle
= rectArea
;
935 region
.RelativeCoordinates
= true;
937 region
.SelectedObject
= selectedObject
;
938 if(!String
.IsNullOrEmpty(series
))
940 region
.SeriesName
= series
;
942 _regionList
.Add( region
);
949 /// Add Hot region to the collection.
951 /// <param name="rectArea">Hot Region rectangle</param>
952 /// <param name="toolTip">Tool Tip Text</param>
953 /// <param name="hRef">HRef string</param>
954 /// <param name="mapAreaAttributes">Map area Attribute string</param>
955 /// <param name="postBackValue">The post back value associated with this item</param>
956 /// <param name="selectedObject">Object which present hot region</param>
957 /// <param name="selectedSubObject">Sub-Object which present hot region</param>
958 /// <param name="type">AxisName of the object which present hot region</param>
959 /// <param name="series">Selected series</param>
961 System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId
= "hRef"),
962 System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId
= "mapAreaAttributes"),
963 System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId
= "postBackValue"),
964 System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId
= "toolTip")
966 internal void AddHotRegion(
970 string mapAreaAttributes
,
971 string postBackValue
,
972 object selectedObject
,
973 object selectedSubObject
,
974 ChartElementType type
,
977 #if !Microsoft_CONTROL
978 if( ( ProcessChartMode
& ProcessMode
.ImageMaps
) == ProcessMode
.ImageMaps
)
980 // Add items to the image map collection
981 if (_common
.ChartPicture
.IsMapEnabled
== true)
983 if(toolTip
.Length
> 0 ||
985 mapAreaAttributes
.Length
> 0 ||
986 postBackValue
.Length
> 0)
988 MapArea area
= new MapArea(
994 ((IChartMapArea
)selectedObject
).Tag
);
995 area
.IsCustom
= false;
996 _common
.ChartPicture
.MapAreas
.Add( area
);
1000 #endif // !Microsoft_CONTROL
1002 if( ( ProcessChartMode
& ProcessMode
.HotRegions
) == ProcessMode
.HotRegions
)
1004 HotRegion region
= new HotRegion();
1006 region
.BoundingRectangle
= rectArea
;
1007 region
.RelativeCoordinates
= true;
1009 region
.SelectedObject
= selectedObject
;
1010 region
.SelectedSubObject
= selectedSubObject
;
1011 if(!String
.IsNullOrEmpty(series
))
1013 region
.SeriesName
= series
;
1015 _regionList
.Add( region
);
1022 /// Add Hot region to the collection.
1024 /// <param name="graph">Chart Graphics Object</param>
1025 /// <param name="path">Graphics path</param>
1026 /// <param name="relativePath">Used relative coordinates for graphics path.</param>
1027 /// <param name="toolTip">Tool Tip Text</param>
1028 /// <param name="hRef">HRef string</param>
1029 /// <param name="mapAreaAttributes">Map area Attribute string</param>
1030 /// <param name="postBackValue">The post back value associated with this item</param>
1031 /// <param name="selectedObject">Object which present hot region</param>
1032 /// <param name="type">AxisName of the object which present hot region</param>
1034 System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId
= "graph"),
1035 System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId
= "hRef"),
1036 System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId
= "mapAreaAttributes"),
1037 System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId
= "postBackValue"),
1038 System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId
= "toolTip")
1040 internal void AddHotRegion( ChartGraphics graph
, GraphicsPath path
, bool relativePath
, string toolTip
, string hRef
, string mapAreaAttributes
, string postBackValue
, object selectedObject
, ChartElementType type
)
1042 #if !Microsoft_CONTROL
1043 if( ( ProcessChartMode
& ProcessMode
.ImageMaps
) == ProcessMode
.ImageMaps
)
1045 if (_common
.ChartPicture
.IsMapEnabled
== true)
1048 if(toolTip
.Length
> 0 ||
1050 mapAreaAttributes
.Length
> 0 ||
1051 postBackValue
.Length
> 0)
1053 _common
.ChartPicture
.MapAreas
.InsertPath(
1066 #endif // !Microsoft_CONTROL
1068 if( ( ProcessChartMode
& ProcessMode
.HotRegions
) == ProcessMode
.HotRegions
)
1071 HotRegion region
= new HotRegion();
1074 region
.Path
= (GraphicsPath
)path
.Clone();
1075 region
.SelectedObject
= selectedObject
;
1076 region
.BoundingRectangle
= path
.GetBounds();
1077 region
.RelativeCoordinates
= relativePath
;
1079 _regionList
.Add( region
);
1085 /// Add Hot region to the collection.
1087 /// <param name="rectArea">Hot Region rectangle</param>
1088 /// <param name="selectedObject">Object which present hot region</param>
1089 /// <param name="type">AxisName of the object which present hot region</param>
1090 /// <param name="relativeCoordinates">Coordinates for rectangle are relative</param>
1091 internal void AddHotRegion( RectangleF rectArea
, object selectedObject
, ChartElementType type
, bool relativeCoordinates
)
1093 this.AddHotRegion( rectArea
, selectedObject
, type
, relativeCoordinates
, false );
1097 /// Add Hot region to the collection.
1099 /// <param name="rectArea">Hot Region rectangle</param>
1100 /// <param name="selectedObject">Object which present hot region</param>
1101 /// <param name="type">AxisName of the object which present hot region</param>
1102 /// <param name="relativeCoordinates">Coordinates for rectangle are relative</param>
1103 /// <param name="insertAtBeginning">Insert the hot region at the beginning of the collection</param>
1104 internal void AddHotRegion( RectangleF rectArea
, object selectedObject
, ChartElementType type
, bool relativeCoordinates
, bool insertAtBeginning
)
1106 if( ( ProcessChartMode
& ProcessMode
.HotRegions
) == ProcessMode
.HotRegions
)
1108 HotRegion region
= new HotRegion();
1110 region
.BoundingRectangle
= rectArea
;
1111 region
.RelativeCoordinates
= relativeCoordinates
;
1113 region
.SelectedObject
= selectedObject
;
1115 if( insertAtBeginning
)
1117 _regionList
.Insert( _regionList
.Count
- 1, region
);
1121 _regionList
.Add( region
);
1127 /// Add Hot region to the collection.
1129 /// <param name="path">Graphics path</param>
1130 /// <param name="relativePath">Used relative coordinates for graphics path.</param>
1131 /// <param name="type">Type of the object which present hot region</param>
1132 /// <param name="selectedObject">Object which present hot region</param>
1133 internal void AddHotRegion(
1136 ChartElementType type
,
1137 object selectedObject
1140 if( ( ProcessChartMode
& ProcessMode
.HotRegions
) == ProcessMode
.HotRegions
)
1143 HotRegion region
= new HotRegion();
1145 region
.SelectedObject
= selectedObject
;
1147 region
.Path
= (GraphicsPath
)path
.Clone();
1148 region
.BoundingRectangle
= path
.GetBounds();
1149 region
.RelativeCoordinates
= relativePath
;
1151 _regionList
.Add( region
);
1157 /// This method search for position in Map Areas which is the first
1158 /// position after Custom areas.
1160 /// <returns>Insert Index</returns>
1161 internal int FindInsertIndex()
1163 int insertIndex
= 0;
1164 #if !Microsoft_CONTROL
1165 foreach (MapArea mapArea
in _common
.ChartPicture
.MapAreas
)
1167 if(!mapArea
.IsCustom
)
1173 #endif // !Microsoft_CONTROL
1179 /// Clears this instance.
1183 foreach (HotRegion hotRegion
in this._regionList
)
1184 hotRegion
.Dispose();
1186 this._regionList
.Clear();
1189 #endregion // Methods
1191 #region IDisposable members
1193 /// Releases unmanaged and - optionally - managed resources
1195 /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
1196 protected virtual void Dispose(bool disposing
)
1200 if (this._regionList
!= null)
1202 foreach (HotRegion hotRegion
in this._regionList
)
1203 hotRegion
.Dispose();
1205 this._regionList
.Clear();
1211 /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
1213 public void Dispose()
1216 GC
.SuppressFinalize(this);
1223 /// The HitTestResult class contains the result of the hit test function.
1226 [AspNetHostingPermission(System
.Security
.Permissions
.SecurityAction
.InheritanceDemand
, Level
= AspNetHostingPermissionLevel
.Minimal
)]
1227 [AspNetHostingPermission(System
.Security
.Permissions
.SecurityAction
.LinkDemand
, Level
= AspNetHostingPermissionLevel
.Minimal
)]
1229 public class HitTestResult
1234 private object _obj
= null;
1235 private Series _series
= null;
1236 private int _dataPoint
= -1;
1237 private ChartArea _chartArea
= null;
1238 private Axis _axis
= null;
1239 private ChartElementType _type
= ChartElementType
.Nothing
;
1240 private object _subObject
= null;
1247 /// Gets or sets the data series object.
1249 public Series Series
1262 /// Gets or sets the data point index.
1264 public int PointIndex
1277 /// Gets or sets the chart area object.
1279 public ChartArea ChartArea
1292 /// Gets or sets the axis object.
1307 /// Gets or sets the chart element type.
1309 public ChartElementType ChartElementType
1322 /// Gets or sets the selected object.
1324 public object Object
1339 /// Gets or sets the selected sub object.
1341 public object SubObject
1358 /// This class represents an array of marker points and
1359 /// the outline path used for visual object selection in the chart.
1362 /// <see cref="OutlinePath"/> may be null for complex objects or objects with two points or fewer.
1365 [AspNetHostingPermission(System
.Security
.Permissions
.SecurityAction
.InheritanceDemand
, Level
= AspNetHostingPermissionLevel
.Minimal
)]
1366 [AspNetHostingPermission(System
.Security
.Permissions
.SecurityAction
.LinkDemand
, Level
= AspNetHostingPermissionLevel
.Minimal
)]
1368 public class ChartElementOutline
: IDisposable
1371 /// Initializes a new instance of the <see cref="ChartElementOutline"/> class.
1373 internal ChartElementOutline()
1375 this.Markers
= new ReadOnlyCollection
<PointF
>( new PointF
[] {});
1379 /// Gets the markers.
1381 /// <value>The markers.</value>
1382 public ReadOnlyCollection
<PointF
> Markers { get; internal set; }
1385 /// Gets or sets the outline path. The result could be null for complex objects and objects with two points or fewer.
1387 /// <value>The outline path.</value>
1388 public GraphicsPath OutlinePath { get; internal set; }
1391 #region IDisposable Members
1394 /// Releases unmanaged and - optionally - managed resources
1396 /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
1397 protected virtual void Dispose(bool disposing
)
1401 if (this.OutlinePath
!= null)
1403 this.OutlinePath
.Dispose();
1404 this.OutlinePath
= null;
1406 this.Markers
= null;
1411 /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
1413 [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
1414 public void Dispose()
1417 GC
.SuppressFinalize(this);
1425 /// This class contains methods used for Windows Forms selection.
1427 internal class Selection
: IServiceProvider
1428 #if Microsoft_CONTROL
1430 #endif //Microsoft_CONTROL
1435 /// The chart service container
1437 private IServiceContainer _service
= null;
1439 #if Microsoft_CONTROL
1442 /// Stores the tooltip of the control.
1444 private ToolTip _toolTip
= new ToolTip();
1447 /// Used by the tooltip - stores the time when the tooltip is activated.
1449 private DateTime _toolTipActivationTime
= DateTime
.Now
;
1452 /// Stores the last mouse move X and Y coordinates, so we can ignore false calls to
1453 /// OnMouseMove generated my the tooltip.
1455 private Point _lastMouseMove
= new Point(int.MinValue
, int.MinValue
);
1458 // ToolTips enabled or disabled from series or legend
1459 private bool _toolTipsEnabled
= false;
1461 // Tool tips enabled flag checked
1462 internal bool enabledChecked
= false;
1464 #endif //Microsoft_CONTROL
1467 #region Constructors
1470 /// Initializes a new instance of the <see cref="Selection"/> class.
1472 /// <param name="service">The service.</param>
1473 internal Selection(IServiceContainer service
)
1475 this._service
= service
;
1476 this._chartControl
= this.ChartControl
;
1477 #if Microsoft_CONTROL
1479 // Set up the tooltip
1480 this._toolTip
.Active
= true;
1481 this._toolTip
.AutoPopDelay
= 30000; // maximum delay possible
1482 this._toolTip
.InitialDelay
= 500;
1483 this._toolTip
.ReshowDelay
= 50;
1484 this._toolTip
.ShowAlways
= true;
1485 this._toolTip
.Active
= false;
1486 #endif //Microsoft_CONTROL
1490 #if Microsoft_CONTROL
1492 /// Releases unmanaged and - optionally - managed resources
1494 /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
1495 private void Dispose(bool disposing
)
1499 if (_toolTip
!= null)
1508 /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
1510 public void Dispose()
1513 GC
.SuppressFinalize(this);
1516 #endif //Microsoft_CONTROL
1518 #endregion //Constructors
1522 private Chart _chartControl
= null;
1524 /// Returns the attached chart control
1526 internal Chart ChartControl
1530 if (this._chartControl
== null)
1532 if (this.ChartPicture
!= null)
1534 this._chartControl
= this.ChartPicture
.Chart
;
1537 return this._chartControl
;
1541 private ChartPicture _chartPicture
= null;
1543 /// Returns the attached ChartPicture
1545 internal ChartPicture ChartPicture
1549 if (this._chartPicture
== null)
1551 this._chartPicture
= ((IServiceProvider
)this).GetService(typeof(ChartImage
)) as ChartPicture
;
1552 if (this._chartPicture
== null)
1554 this._chartPicture
= ((IServiceProvider
)this).GetService(typeof(ChartPicture
)) as ChartPicture
;
1557 return this._chartPicture
;
1561 private Data
.DataManager _dataManager
= null;
1563 /// Gets the chart data manager ( for series access )
1565 internal Data
.DataManager DataManager
1569 if (this._dataManager
== null)
1571 this._dataManager
= ((IServiceProvider
)this).GetService(typeof(Data
.DataManager
)) as Data
.DataManager
;
1573 return this._dataManager
;
1578 /// Gets the chart ChartGraphics
1580 internal ChartGraphics Graph
1584 if (this.ChartPicture
!= null)
1586 return this.ChartPicture
.Common
.graph
;
1592 #endregion //Private Properties
1597 #if Microsoft_CONTROL
1599 /// Checks if tooltips are enabled
1601 /// <returns>true if tooltips enabled</returns>
1602 private bool IsToolTipsEnabled()
1604 // Enabled checked. Don’t check every time series
1605 // and data points for tooltips.
1606 if( enabledChecked
)
1608 return _toolTipsEnabled
;
1611 enabledChecked
= true;
1617 foreach( Annotation annotation
in _chartControl
.Annotations
)
1620 if( annotation
.ToolTip
.Length
> 0 )
1623 _toolTipsEnabled
= true;
1630 foreach( Series series
in _chartControl
.Series
)
1632 // Check series tooltips
1633 if( series
.ToolTip
.Length
> 0 ||
1634 series
.LegendToolTip
.Length
> 0 ||
1635 series
.LabelToolTip
.Length
> 0)
1638 _toolTipsEnabled
= true;
1643 // Check if custom properties (Pie collected slice) that create tooltips are used
1644 if(series
.IsCustomPropertySet(Utilities
.CustomPropertyName
.CollectedToolTip
))
1647 _toolTipsEnabled
= true;
1652 // Check point tooltips only for "non-Fast" chart types
1653 if( !series
.IsFastChartType() )
1656 foreach( DataPoint point
in series
.Points
)
1659 if( point
.ToolTip
.Length
> 0 ||
1660 point
.LegendToolTip
.Length
> 0 ||
1661 point
.LabelToolTip
.Length
> 0)
1664 _toolTipsEnabled
= true;
1671 // Legend items loop
1672 foreach( Legend legend
in _chartControl
.Legends
)
1674 // Check custom legend items
1675 foreach( LegendItem legendItem
in legend
.CustomItems
)
1678 if( legendItem
.ToolTip
.Length
> 0 )
1680 _toolTipsEnabled
= true;
1685 // Check all custom cells in the legend item
1686 foreach(LegendCell legendCell
in legendItem
.Cells
)
1688 if(legendCell
.ToolTip
.Length
> 0)
1690 _toolTipsEnabled
= true;
1698 // Iterate through legend columns
1699 foreach(LegendCellColumn legendColumn
in legend
.CellColumns
)
1701 if(legendColumn
.ToolTip
.Length
> 0)
1703 _toolTipsEnabled
= true;
1711 foreach( Title title
in _chartControl
.Titles
)
1714 if( title
.ToolTip
.Length
> 0 )
1716 _toolTipsEnabled
= true;
1722 foreach( ChartArea area
in _chartControl
.ChartAreas
)
1725 // Check if chart area is visible
1730 foreach(Axis axis
in area
.Axes
)
1734 if( axis
.ToolTip
.Length
> 0 )
1736 _toolTipsEnabled
= true;
1742 foreach(StripLine stripLine
in axis
.StripLines
)
1745 if( stripLine
.ToolTip
.Length
> 0 )
1747 _toolTipsEnabled
= true;
1751 // Check custom labels
1752 foreach(CustomLabel customLabel
in axis
.CustomLabels
)
1754 if( customLabel
.ToolTip
.Length
> 0 )
1756 _toolTipsEnabled
= true;
1764 // ToolTips disabled
1765 _toolTipsEnabled
= false;
1769 [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily",
1770 Justification
= "Too large of a code change to justify making this change")]
1771 internal string EvaluateToolTip(System
.Windows
.Forms
.MouseEventArgs e
)
1775 ChartElementType type
;
1778 string toolTipText
= " ";
1780 HitTestResult hitTest
= this.HitTest(e
.X
, e
.Y
, true);
1782 type
= hitTest
.ChartElementType
;
1783 dataPointIndex
= hitTest
.PointIndex
;
1784 seriesName
= hitTest
.Series
!= null ? hitTest
.Series
.Name
: String
.Empty
;
1785 obj
= hitTest
.Object
;
1786 subObj
= hitTest
.SubObject
;
1789 // Get tooltips from data points
1790 if (type
== ChartElementType
.DataPoint
)
1792 if (_chartControl
.Series
.IndexOf(seriesName
) >= 0 &&
1793 dataPointIndex
>= 0 &&
1794 dataPointIndex
< _chartControl
.Series
[seriesName
].Points
.Count
)
1796 // Take tool tip from data point
1797 toolTipText
= _chartControl
.Series
[seriesName
].Points
[dataPointIndex
].ReplaceKeywords(_chartControl
.Series
[seriesName
].Points
[dataPointIndex
].ToolTip
);
1801 DataPoint dataPoint
= obj
as DataPoint
;
1802 if (dataPoint
!= null)
1804 // Take tool tip from data point
1805 toolTipText
= dataPoint
.ReplaceKeywords(dataPoint
.ToolTip
);
1812 // Get tooltips from data points
1813 if (type
== ChartElementType
.DataPointLabel
)
1815 if (_chartControl
.Series
.IndexOf(seriesName
) >= 0 &&
1816 dataPointIndex
>= 0 &&
1817 dataPointIndex
< _chartControl
.Series
[seriesName
].Points
.Count
)
1819 // Take tool tip from data point
1820 toolTipText
= _chartControl
.Series
[seriesName
].Points
[dataPointIndex
].ReplaceKeywords(_chartControl
.Series
[seriesName
].Points
[dataPointIndex
].LabelToolTip
);
1825 // Get tooltips from custom label
1826 if (type
== ChartElementType
.AxisLabels
&&
1829 toolTipText
= ((CustomLabel
)obj
).ToolTip
;
1835 // Get tooltips from data points
1836 else if (type
== ChartElementType
.Annotation
&& obj
!= null && obj
is Annotation
)
1838 // Take tool tip from data point
1839 toolTipText
= ((Annotation
)obj
).ReplaceKeywords(((Annotation
)obj
).ToolTip
);
1842 // Get tooltips from axis
1843 else if (type
== ChartElementType
.Axis
&& obj
!= null && obj
is Axis
)
1845 // Take tool tip from strip line
1846 toolTipText
= ((Axis
)obj
).ToolTip
;
1849 // Get tooltips from strip lines
1850 else if (type
== ChartElementType
.StripLines
&& obj
!= null && obj
is StripLine
)
1852 // Take tool tip from strip line
1853 toolTipText
= ((StripLine
)obj
).ToolTip
;
1856 // Get tooltips from data points
1857 else if (type
== ChartElementType
.Title
&& obj
!= null && obj
is Title
)
1859 // Take tool tip from data point
1860 toolTipText
= ((Title
)obj
).ToolTip
;
1862 } // Get tooltips for legend items
1864 // Get tooltips for legend items
1865 else if (type
== ChartElementType
.LegendItem
)
1867 // Take tool tip from legend item
1868 toolTipText
= ((LegendItem
)obj
).ToolTip
;
1871 // Check if cell has it's own tooltip
1872 LegendCell legendCell
= subObj
as LegendCell
;
1873 if (legendCell
!= null && legendCell
.ToolTip
.Length
> 0)
1875 toolTipText
= legendCell
.ToolTip
;
1879 // Check if series is associated with legend item
1880 if (toolTipText
.Length
== 0 &&
1881 seriesName
.Length
> 0 &&
1882 _chartControl
.Series
.IndexOf(seriesName
) >= 0)
1884 // Take tool tip from data point
1885 if (dataPointIndex
== -1)
1887 if (seriesName
.Length
> 0)
1889 // Take tool tip from series
1890 toolTipText
= _chartControl
.Series
[seriesName
].ReplaceKeywords(_chartControl
.Series
[seriesName
].LegendToolTip
);
1895 if (dataPointIndex
>= 0 &&
1896 dataPointIndex
< _chartControl
.Series
[seriesName
].Points
.Count
)
1898 // Take tool tip from data point
1899 toolTipText
= _chartControl
.Series
[seriesName
].Points
[dataPointIndex
].ReplaceKeywords(_chartControl
.Series
[seriesName
].Points
[dataPointIndex
].LegendToolTip
);
1905 // Set event arguments
1906 ToolTipEventArgs args
= new ToolTipEventArgs(e
.X
, e
.Y
, toolTipText
, hitTest
);
1909 _chartControl
.OnGetToolTipText(args
);
1911 return args
.Text
.Trim();
1917 /// Mouse move event handler.
1919 /// <param name="sender">Sender</param>
1920 /// <param name="e">Arguments</param>
1921 internal void Selection_MouseMove(object sender
, System
.Windows
.Forms
.MouseEventArgs e
)
1924 // Ignore false calls to OnMouseMove caused by the tootip control.
1925 if (e
.X
== this._lastMouseMove
.X
&& e
.Y
== this._lastMouseMove
.Y
)
1931 this._lastMouseMove
.X
= e
.X
;
1932 this._lastMouseMove
.Y
= e
.Y
;
1935 // Event is not active and tooltip properties are nor set.
1936 if (!IsToolTipsEnabled() && !_chartControl
.IsToolTipEventUsed())
1941 string newToolTipText
= this.EvaluateToolTip(e
);
1943 if (!String
.IsNullOrEmpty(newToolTipText
))
1945 string oldToolTipText
= this._toolTip
.GetToolTip(this._chartControl
);
1946 TimeSpan timeSpan
= DateTime
.Now
.Subtract(this._toolTipActivationTime
);
1947 if (oldToolTipText
!= newToolTipText
|| timeSpan
.Milliseconds
> 600)
1949 // Activate the tooltip
1950 this._toolTip
.Active
= false;
1951 this._toolTip
.SetToolTip(this._chartControl
, newToolTipText
);
1952 this._toolTip
.Active
= true;
1953 this._toolTipActivationTime
= DateTime
.Now
;
1958 // We do not have a tooltip, so deactivate it
1959 this._toolTip
.Active
= false;
1960 this._toolTip
.SetToolTip(this._chartControl
, string.Empty
);
1964 #endif //Microsoft_CONTROL
1966 #endregion //Tooltips
1972 /// Call this method to determine the chart element,
1973 /// if any, that is located at a point defined by the given X and Y
1975 /// <seealso cref="HitTestResult"/></summary>
1976 /// <param name="x">The X coordinate for the point in question.
1977 /// Often obtained from a parameter in an event
1978 /// (e.g. the X parameter value in the MouseDown event).</param>
1979 /// <param name="y">The Y coordinate for the point in question.
1980 /// Often obtained from a parameter in an event
1981 /// (e.g. the Y parameter value in the MouseDown event).</param>
1982 /// <param name="requestedElementTypes">
1983 /// An array of type which specify the types
1984 /// to test for, on order to filter the result. If omitted checking for
1985 /// elementTypes will be ignored and all kind of elementTypes will be
1988 /// <param name="ignoreTransparent">Indicates that transparent
1989 /// elements should be ignored.</param>
1991 /// A array of <see cref="HitTestResult"/> objects,
1992 /// which provides information concerning the chart element
1993 /// (if any) that is at the specified location. Result contains at least
1994 /// one element, which could be ChartElementType.Nothing.
1995 /// The objects in the result are sorted in from top to bottom of
1996 /// different layers of control. </returns>
1997 /// <remarks>Call this method to determine the gauge element
1998 /// (if any) that is located at a specified point. Often this method is used in
1999 /// some mouse-related event (e.g. MouseDown)
2000 /// to determine what gauge element the end-user clicked on.
2001 /// The X and Y mouse coordinates obtained from the
2002 /// event parameters are then used for the X and Y parameter
2003 /// values of this method call. The returned
2004 /// <see cref="HitTestResult"/> object's properties
2005 /// can then be used to determine what chart element was clicked on,
2006 /// and also provides a reference to the actual object selected (if
2008 internal HitTestResult
[] HitTest(int x
, int y
, bool ignoreTransparent
, params ChartElementType
[] requestedElementTypes
)
2010 List
<HitTestResult
> result
= new List
<HitTestResult
>();
2011 ArrayList regionList
= this.ChartPicture
.Common
.HotRegionsList
.List
;
2013 if (regionList
.Count
== 0)
2015 this.ChartPicture
.PaintOffScreen();
2018 string alowedElements
= String
.Empty
;
2019 if (requestedElementTypes
.Length
> 0)
2021 StringBuilder builder
= new StringBuilder();
2022 foreach (ChartElementType elementType
in requestedElementTypes
)
2024 builder
.Append(elementType
.ToString() + ";");
2026 alowedElements
= builder
.ToString();
2033 RectangleF newMouseRect
;
2035 // Find mouse position in relative and absolute coordinates
2036 RectangleF mouseRect
= new RectangleF(x
- 1, y
- 1, 2, 2);
2037 relativeX
= this.Graph
.GetRelativePoint(new PointF(x
, y
)).X
;
2038 relativeY
= this.Graph
.GetRelativePoint(new PointF(x
, y
)).Y
;
2039 RectangleF relativeMouseRect
= this.Graph
.GetRelativeRectangle(mouseRect
);
2041 // Try to pass through series object in design time.
2042 // The series ussualy contain autogenerated points with short lifetime - during painting;
2043 // This hit test result will be used in VS2005 desing time click.
2044 for (int index
= regionList
.Count
- 1; index
>= 0; index
--)
2046 HotRegion region
= (HotRegion
)regionList
[index
];
2048 // Check if only looking for specific chart element type
2049 if (!String
.IsNullOrEmpty(alowedElements
) && alowedElements
.IndexOf(region
.Type
.ToString() + ";", StringComparison
.Ordinal
) == -1)
2055 // Change coordinates if relative path is used
2056 if (region
.RelativeCoordinates
)
2060 newMouseRect
= relativeMouseRect
;
2066 newMouseRect
= mouseRect
;
2070 // Check if series name and point index are valid
2071 if (region
.SeriesName
.Length
> 0 &&
2072 (this.ChartControl
.Series
.IndexOf(region
.SeriesName
) < 0 || region
.PointIndex
>= this.ChartControl
.Series
[region
.SeriesName
].Points
.Count
)
2078 // Check if transparent chart elements should be ignored
2079 if (ignoreTransparent
&& IsElementTransparent(region
))
2083 // Check intersection with bounding rectangle
2084 if (region
.BoundingRectangle
.IntersectsWith(newMouseRect
))
2086 bool pointVisible
= false;
2088 if (region
.Path
!= null)
2090 // If there is more then one graphical path split them and create
2091 // image maps for every graphical path separately.
2092 GraphicsPathIterator iterator
= new GraphicsPathIterator(region
.Path
);
2094 // There is more then one path.
2095 if (iterator
.SubpathCount
> 1)
2097 GraphicsPath subPath
= new GraphicsPath();
2098 while (iterator
.NextMarker(subPath
) > 0 && pointVisible
== false)
2100 if (subPath
.IsVisible(newX
, newY
))
2102 pointVisible
= true;
2108 // There is only one path
2109 else if (region
.Path
.IsVisible(newX
, newY
))
2111 pointVisible
= true;
2116 // Point is inside bounding rectangle and path is not specified
2117 pointVisible
= true;
2120 // Check if point is inside the hot region
2123 HitTestResult hitTestToAdd
= this.GetHitTestResult(
2127 region
.SelectedObject
,
2128 region
.SelectedSubObject
2131 int elementIndex
= result
.FindIndex(
2132 delegate(HitTestResult test
)
2135 (test
.ChartElementType
== hitTestToAdd
.ChartElementType
) &&
2136 (test
.Object
== hitTestToAdd
.Object
) &&
2137 (test
.SubObject
== hitTestToAdd
.SubObject
) &&
2138 (test
.Series
== hitTestToAdd
.Series
) &&
2139 (test
.PointIndex
== hitTestToAdd
.PointIndex
)
2148 if (elementIndex
== -1)
2150 result
.Add(hitTestToAdd
);
2155 if (result
.Count
== 0)
2157 result
.Add(this.GetHitTestResult(String
.Empty
, 0, ChartElementType
.Nothing
, null, null));
2159 return result
.ToArray();
2163 /// This method performs the hit test and returns a HitTestResult objects.
2165 /// <param name="x">X coordinate</param>
2166 /// <param name="y">Y coordinate</param>
2167 /// <returns>Hit test result object</returns>
2168 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
2169 Justification
= "X and Y are cartesian coordinates and well understood")]
2170 internal HitTestResult
HitTest(int x
, int y
)
2172 return this.HitTest(x
, y
, false, new ChartElementType
[] {})[0];
2176 /// This method performs the hit test and returns a HitTestResult object.
2178 /// <param name="x">X coordinate</param>
2179 /// <param name="y">Y coordinate</param>
2180 /// <param name="ignoreTransparent">Indicates that transparent elements should be ignored.</param>
2181 /// <returns>Hit test result object</returns>
2182 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
2183 Justification
= "X and Y are cartesian coordinates and well understood")]
2184 public HitTestResult
HitTest(int x
, int y
, bool ignoreTransparent
)
2186 return this.HitTest(x
, y
, ignoreTransparent
, new ChartElementType
[] { }
)[0];
2190 /// This method performs the hit test and returns a HitTestResult object.
2192 /// <param name="x">X coordinate</param>
2193 /// <param name="y">Y coordinate</param>
2194 /// <param name="requestedElement">Only this chart element will be hit tested.</param>
2195 /// <returns>Hit test result object</returns>
2196 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
2197 Justification
= "X and Y are cartesian coordinates and well understood")]
2198 public HitTestResult
HitTest(int x
, int y
, ChartElementType requestedElement
)
2200 return this.HitTest(x
, y
, false, requestedElement
)[0];
2204 /// Checks if chart element associated with hot region has transparent background.
2206 /// <param name="region">Element hot region.</param>
2207 /// <returns>True if chart element is transparent.</returns>
2208 private bool IsElementTransparent(HotRegion region
)
2210 bool isTransparent
= false;
2212 if (region
.Type
== ChartElementType
.DataPoint
)
2214 if (this.ChartControl
!= null)
2216 DataPoint dataPoint
= region
.SelectedObject
as DataPoint
;
2217 if (region
.SeriesName
.Length
> 0)
2219 dataPoint
= this.ChartControl
.Series
[region
.SeriesName
].Points
[region
.PointIndex
];
2221 if (dataPoint
!= null && dataPoint
.Color
== Color
.Transparent
)
2223 isTransparent
= true;
2227 else if (region
.SelectedObject
is Axis
)
2229 if (((Axis
)region
.SelectedObject
).LineColor
== Color
.Transparent
)
2231 isTransparent
= true;
2234 else if (region
.SelectedObject
is ChartArea
)
2236 if (((ChartArea
)region
.SelectedObject
).BackColor
== Color
.Transparent
)
2238 isTransparent
= true;
2241 else if (region
.SelectedObject
is Legend
)
2243 if (((Legend
)region
.SelectedObject
).BackColor
== Color
.Transparent
)
2245 isTransparent
= true;
2248 else if (region
.SelectedObject
is Grid
)
2250 if (((Grid
)region
.SelectedObject
).LineColor
== Color
.Transparent
)
2252 isTransparent
= true;
2255 else if (region
.SelectedObject
is StripLine
)
2257 if (((StripLine
)region
.SelectedObject
).BackColor
== Color
.Transparent
)
2259 isTransparent
= true;
2262 else if (region
.SelectedObject
is TickMark
)
2264 if (((TickMark
)region
.SelectedObject
).LineColor
== Color
.Transparent
)
2266 isTransparent
= true;
2269 else if (region
.SelectedObject
is Title
)
2271 Title title
= (Title
)region
.SelectedObject
;
2272 if ((title
.Text
.Length
== 0 || title
.ForeColor
== Color
.Transparent
) &&
2273 (title
.BackColor
== Color
.Transparent
|| title
.BackColor
.IsEmpty
))
2275 isTransparent
= true;
2279 return isTransparent
;
2283 /// Returns Hit Test Result object
2285 /// <param name="seriesName">Data series Name</param>
2286 /// <param name="pointIndex">Data point index</param>
2287 /// <param name="type">Selected Chart element type</param>
2288 /// <param name="obj">Selected object</param>
2289 /// <param name="subObject">Selected sub object</param>
2290 /// <returns>Hit test result object</returns>
2291 [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily",
2292 Justification
= "Too large of a code change to justify making this change")]
2293 internal HitTestResult
GetHitTestResult(
2296 ChartElementType type
,
2300 HitTestResult result
= new HitTestResult();
2301 Chart chart
= this.ChartControl
;
2302 // If data point is selected convert series
2303 // name to series object.
2304 if (seriesName
.Length
> 0)
2306 result
.Series
= chart
.Series
[seriesName
];
2310 result
.Object
= obj
;
2312 result
.SubObject
= subObject
;
2314 result
.PointIndex
= pointIndex
;
2315 result
.ChartElementType
= type
;
2317 #if Microsoft_CONTROL
2318 AxisScrollBar scrollBar
;
2319 #endif // Microsoft_CONTROL
2323 case ChartElementType
.Axis
:
2324 Axis axis
= (Axis
)obj
;
2328 result
.ChartArea
= axis
.ChartArea
;
2331 case ChartElementType
.DataPoint
:
2333 if (chart
.Series
.IndexOf(seriesName
) >= 0 &&
2334 pointIndex
< chart
.Series
[seriesName
].Points
.Count
)
2336 DataPoint dataPoint
= chart
.Series
[seriesName
].Points
[pointIndex
];
2338 result
.ChartArea
= chart
.ChartAreas
[dataPoint
.series
.ChartArea
];
2339 result
.Object
= dataPoint
;
2344 case ChartElementType
.DataPointLabel
:
2346 if (chart
.Series
.IndexOf(seriesName
) >= 0 &&
2347 pointIndex
< chart
.Series
[seriesName
].Points
.Count
)
2349 DataPoint dataPoint
= chart
.Series
[seriesName
].Points
[pointIndex
];
2351 result
.ChartArea
= chart
.ChartAreas
[dataPoint
.series
.ChartArea
];
2352 result
.Object
= dataPoint
;
2357 case ChartElementType
.Gridlines
:
2358 Grid gridLines
= (Grid
)obj
;
2359 result
.Axis
= gridLines
.Axis
;
2360 if (gridLines
.Axis
!= null)
2362 result
.ChartArea
= gridLines
.Axis
.ChartArea
;
2365 case ChartElementType
.LegendArea
:
2367 result
.ChartArea
= null;
2369 case ChartElementType
.LegendItem
:
2370 result
.PointIndex
= ((LegendItem
)obj
).SeriesPointIndex
;
2372 result
.ChartArea
= null;
2374 case ChartElementType
.PlottingArea
:
2375 ChartArea area
= (ChartArea
)obj
;
2377 result
.ChartArea
= area
;
2379 case ChartElementType
.StripLines
:
2380 StripLine stripLines
= (StripLine
)obj
;
2381 result
.Axis
= stripLines
.Axis
;
2382 if (stripLines
.Axis
!= null)
2384 result
.ChartArea
= stripLines
.Axis
.ChartArea
;
2387 case ChartElementType
.TickMarks
:
2388 TickMark tickMarks
= (TickMark
)obj
;
2389 result
.Axis
= tickMarks
.Axis
;
2390 if (tickMarks
.Axis
!= null)
2392 result
.ChartArea
= tickMarks
.Axis
.ChartArea
;
2395 case ChartElementType
.Title
:
2397 result
.ChartArea
= null;
2399 case ChartElementType
.AxisLabels
:
2400 if (obj
is CustomLabel
)
2402 CustomLabel label
= (CustomLabel
)obj
;
2403 result
.Axis
= label
.Axis
;
2404 result
.ChartArea
= label
.Axis
!=null ? label
.Axis
.ChartArea
: null;
2407 case ChartElementType
.AxisLabelImage
:
2408 if (obj
is CustomLabel
)
2410 CustomLabel label
= (CustomLabel
)obj
;
2411 result
.Axis
= label
.Axis
;
2412 result
.ChartArea
= label
.Axis
!=null ? label
.Axis
.ChartArea
: null;
2415 case ChartElementType
.AxisTitle
:
2418 result
.Axis
= (Axis
)obj
;
2419 result
.ChartArea
= result
.Axis
.ChartArea
;
2422 #if Microsoft_CONTROL
2423 case ChartElementType
.ScrollBarLargeDecrement
:
2424 scrollBar
= (AxisScrollBar
)obj
;
2425 result
.Axis
= scrollBar
.axis
;
2426 if (scrollBar
.axis
!= null)
2428 result
.ChartArea
= scrollBar
.axis
.ChartArea
;
2431 case ChartElementType
.ScrollBarLargeIncrement
:
2432 scrollBar
= (AxisScrollBar
)obj
;
2433 result
.Axis
= scrollBar
.axis
;
2434 if (scrollBar
.axis
!= null)
2436 result
.ChartArea
= scrollBar
.axis
.ChartArea
;
2439 case ChartElementType
.ScrollBarSmallDecrement
:
2440 scrollBar
= (AxisScrollBar
)obj
;
2441 result
.Axis
= scrollBar
.axis
;
2442 if (scrollBar
.axis
!= null)
2444 result
.ChartArea
= scrollBar
.axis
.ChartArea
;
2447 case ChartElementType
.ScrollBarSmallIncrement
:
2448 scrollBar
= (AxisScrollBar
)obj
;
2449 result
.Axis
= scrollBar
.axis
;
2450 if (scrollBar
.axis
!= null)
2452 result
.ChartArea
= scrollBar
.axis
.ChartArea
;
2455 case ChartElementType
.ScrollBarThumbTracker
:
2456 scrollBar
= (AxisScrollBar
)obj
;
2457 result
.Axis
= scrollBar
.axis
;
2458 if (scrollBar
.axis
!= null)
2460 result
.ChartArea
= scrollBar
.axis
.ChartArea
;
2463 #endif // Microsoft_CONTROL
2465 case ChartElementType
.Annotation
:
2467 result
.ChartArea
= null;
2473 #endregion //HitTest
2478 /// Gets the chart element outline.
2480 /// <param name="chartObject">The chart object.</param>
2481 /// <param name="elementType">Type of the element.</param>
2482 /// <returns></returns>
2483 internal ChartElementOutline
GetChartElementOutline(object chartObject
, ChartElementType elementType
)
2486 if (chartObject
== null)
2487 throw new ArgumentNullException("chartObject");
2490 ChartElementOutline result
= new ChartElementOutline();
2491 chartObject
= this.GetAutoGeneratedObject(chartObject
);
2492 ArrayList list
= this.GetMarkers(chartObject
, elementType
);
2493 result
.Markers
= new ReadOnlyCollection
<PointF
>((PointF
[])list
.ToArray(typeof(PointF
)));
2494 result
.OutlinePath
= GetGraphicsPath(list
, chartObject
, elementType
);
2498 #endregion //Outline
2503 /// Gets the graphics path.
2505 /// <param name="markers">The markers.</param>
2506 /// <param name="chartObject">The chart object.</param>
2507 /// <param name="elementType">Type of the element.</param>
2508 /// <returns></returns>
2509 private GraphicsPath
GetGraphicsPath(IList markers
, object chartObject
, ChartElementType elementType
)
2511 bool chartArea3D
= false;
2512 ChartArea chartArea
= chartObject
as ChartArea
;
2513 if (chartArea
!= null && elementType
== ChartElementType
.PlottingArea
)
2515 chartArea3D
= IsArea3D(chartArea
);
2517 if (elementType
!= ChartElementType
.DataPoint
&&
2518 elementType
!= ChartElementType
.Gridlines
&&
2519 elementType
!= ChartElementType
.StripLines
&&
2520 elementType
!= ChartElementType
.TickMarks
&&
2524 GraphicsPath path
= new GraphicsPath();
2525 PointF
[] points
= new PointF
[markers
.Count
];
2526 markers
.CopyTo(points
, 0);
2527 if (points
.Length
> 3)
2529 if (elementType
== ChartElementType
.DataPointLabel
)
2531 for (int i
= 0; i
< points
.Length
; i
+= 4)
2533 RectangleF rect
= RectangleF
.FromLTRB(points
[i
].X
, points
[i
].Y
, points
[i
+ 2].X
, points
[i
+ 2].Y
);
2535 path
.AddRectangle(Rectangle
.Round(rect
));
2540 if (points
.Length
== 4)
2542 Point
[] pointsAlligned
= new Point
[points
.Length
];
2543 for (int i
= 0; i
< points
.Length
; i
++)
2545 pointsAlligned
[i
] = Point
.Round(points
[i
]);
2547 path
.AddPolygon(pointsAlligned
);
2551 path
.AddPolygon(points
);
2560 private static Int32
GetDataPointIndex(DataPoint dataPoint
)
2562 int pointIndex
= -1;
2563 if (dataPoint
!= null && dataPoint
.series
!= null)
2565 pointIndex
= dataPoint
.series
.Points
.IndexOf(dataPoint
);
2566 if (pointIndex
== -1 && dataPoint
.IsCustomPropertySet("OriginalPointIndex"))
2568 if (!Int32
.TryParse(dataPoint
.GetCustomProperty("OriginalPointIndex"), out pointIndex
))
2576 /// Gets the auto generated object.
2578 /// <param name="chartObject">The chart object.</param>
2579 /// <returns></returns>
2580 private object GetAutoGeneratedObject(object chartObject
)
2582 DataPoint dataPoint
= chartObject
as DataPoint
;
2583 if (dataPoint
!= null)
2585 if (dataPoint
.series
!= null)
2587 string seriesName
= dataPoint
.series
.Name
;
2588 int pointIndex
= dataPoint
.series
.Points
.IndexOf(dataPoint
);
2589 if (this.ChartControl
.Series
.IndexOf(seriesName
) != -1)
2591 Series series
= this.ChartControl
.Series
[seriesName
];
2592 if (series
.Points
.Contains(dataPoint
))
2596 if (pointIndex
>= 0)
2598 if (series
.Points
.Count
> pointIndex
)
2600 return series
.Points
[pointIndex
];
2607 Series asSeries
= chartObject
as Series
;
2608 if (asSeries
!= null)
2610 if (this.ChartControl
.Series
.Contains(asSeries
))
2614 if (this.ChartControl
.Series
.IndexOf(asSeries
.Name
) != -1)
2616 return this.ChartControl
.Series
[asSeries
.Name
];
2623 /// Gets the hot regions.
2625 /// <param name="cntxObj">The CNTX obj.</param>
2626 /// <param name="elementType">Type of the element.</param>
2627 /// <returns></returns>
2628 private HotRegion
[] GetHotRegions(object cntxObj
, ChartElementType elementType
)
2630 ArrayList result
= new ArrayList();
2631 HotRegionsList hrList
= this.ChartPicture
.Common
.HotRegionsList
;
2632 string dataPointSeries
= String
.Empty
;
2633 int dataPointIndex
= -1;
2635 for (int i
= hrList
.List
.Count
- 1; i
>= 0; i
--)
2637 HotRegion rgn
= (HotRegion
)hrList
.List
[i
];
2638 if (rgn
.Type
== elementType
)
2642 case ChartElementType
.LegendItem
:
2643 LegendItem legendItem
= cntxObj
as LegendItem
;
2644 if (legendItem
!= null)
2646 if (((LegendItem
)rgn
.SelectedObject
).Name
== legendItem
.Name
)
2652 case ChartElementType
.AxisLabelImage
:
2653 case ChartElementType
.AxisLabels
:
2654 CustomLabel label1
= cntxObj
as CustomLabel
;
2655 CustomLabel label2
= rgn
.SelectedObject
as CustomLabel
;
2658 if (label1
!= null && label2
!= null)
2660 if (label1
.Axis
== label2
.Axis
)
2662 if (label1
.FromPosition
== label2
.FromPosition
&&
2663 label1
.ToPosition
== label2
.ToPosition
&&
2664 label1
.RowIndex
== label2
.RowIndex
)
2666 if (rgn
.Path
== null)
2676 Axis axis
= cntxObj
as Axis
;
2679 if (axis
== label2
.Axis
)
2681 if (rgn
.Path
== null)
2689 case ChartElementType
.DataPointLabel
:
2690 case ChartElementType
.DataPoint
:
2691 DataPoint dataPoint
= cntxObj
as DataPoint
;
2692 if (dataPoint
!= null)
2694 if (String
.IsNullOrEmpty(dataPointSeries
) || dataPointIndex
== -1)
2696 dataPointSeries
= dataPoint
.series
.Name
;
2697 dataPointIndex
= GetDataPointIndex(dataPoint
);
2699 if (rgn
.PointIndex
== dataPointIndex
&& rgn
.SeriesName
== dataPointSeries
)
2706 DataPointCollection dataPointCollection
= cntxObj
as DataPointCollection
;
2707 if (dataPointCollection
!= null)
2709 cntxObj
= dataPointCollection
.series
;
2711 Series series
= cntxObj
as Series
;
2714 if (String
.IsNullOrEmpty(dataPointSeries
) || dataPointIndex
== -1)
2716 dataPointSeries
= series
.Name
;
2718 if (rgn
.SeriesName
== dataPointSeries
)
2727 if (rgn
.SelectedObject
== cntxObj
)
2735 return (HotRegion
[])result
.ToArray(typeof(HotRegion
));
2741 /// Gets the markers from regions.
2743 /// <param name="chartObject">The chart object.</param>
2744 /// <param name="elementType">Type of the element.</param>
2745 /// <returns></returns>
2746 [System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
2747 private ArrayList
GetMarkersFromRegions(object chartObject
, ChartElementType elementType
)
2749 ArrayList list
= new ArrayList();
2750 HotRegion
[] regions
= this.GetHotRegions(chartObject
, elementType
);
2751 ChartGraphics graph
= this.Graph
;
2754 Grid grid
= chartObject
as Grid
;
2757 foreach (HotRegion rgn
in regions
)
2759 if (!IsArea3D(grid
.Axis
.ChartArea
))
2761 if (IsChartAreaCircular(grid
.Axis
.ChartArea
))
2763 GraphicsPathIterator iterator
= new GraphicsPathIterator(rgn
.Path
);
2765 // There is more then one path.
2766 if (iterator
.SubpathCount
> 1)
2768 GraphicsPath subPath
= new GraphicsPath();
2769 while (iterator
.NextMarker(subPath
) > 0)
2771 rect
= subPath
.GetBounds();
2772 list
.Add(new PointF(rect
.Left
+ rect
.Width
/ 2, rect
.Top
));
2773 list
.Add(new PointF(rect
.Right
, rect
.Top
+ rect
.Height
/ 2));
2774 list
.Add(new PointF(rect
.Right
- rect
.Width
/ 2, rect
.Bottom
));
2775 list
.Add(new PointF(rect
.Left
, rect
.Bottom
- rect
.Height
/ 2));
2783 rect
= this.GetHotRegionRectangle(rgn
, RectangleF
.Empty
, elementType
);
2786 if (grid
.GetAxis().AxisPosition
== AxisPosition
.Bottom
||
2787 grid
.GetAxis().AxisPosition
== AxisPosition
.Top
)
2789 rect
.Offset(rect
.Width
/ 2, 0);
2794 rect
.Offset(0, rect
.Height
/ 2);
2798 list
.AddRange(this.GetMarkers(rect
, false));
2803 PointF
[] points
= rgn
.Path
.PathPoints
;
2804 for (int i
= 0; i
< points
.Length
- 3; i
= i
+ 4)
2805 { //Each gridline has a corresponding set of 4 points in the path
2806 //One of the ends of a gridline is in the middle the line between points #0 and #3
2807 //Another ends of a gridline is in the middle the line between points #1 and #2
2808 //So we find those middles and put a marks to the ends of the gridline.
2809 PointF middleP0P3
= new PointF((points
[i
].X
+ points
[i
+ 3].X
) / 2f
, (points
[i
].Y
+ points
[i
+ 3].Y
) / 2f
);
2810 PointF middleP1P2
= new PointF((points
[i
+ 1].X
+ points
[i
+ 2].X
) / 2f
, (points
[i
+ 1].Y
+ points
[i
+ 2].Y
) / 2f
);
2811 list
.Add(graph
.GetAbsolutePoint(middleP0P3
));
2812 list
.Add(graph
.GetAbsolutePoint(middleP1P2
));
2819 DataPoint dataPoint
= chartObject
as DataPoint
;
2820 if (dataPoint
!= null && elementType
!= ChartElementType
.DataPointLabel
)
2822 rect
= Rectangle
.Empty
;
2823 Series series
= dataPoint
.series
;
2824 if (this.ChartControl
.ChartAreas
.IndexOf(series
.ChartArea
) == -1)
2828 ChartArea area
= this.ChartControl
.ChartAreas
[series
.ChartArea
];
2829 PointF pp
= this.Transform3D(area
, dataPoint
);
2830 if (!(float.IsNaN(pp
.X
) || float.IsNaN(pp
.Y
)))
2832 list
.Add(graph
.GetAbsolutePoint(pp
));
2837 Axis axis
= chartObject
as Axis
;
2838 if (axis
!= null && elementType
== ChartElementType
.AxisTitle
)
2840 foreach (HotRegion rgn
in regions
)
2842 if (!IsArea3D(axis
.ChartArea
))
2844 rect
= this.GetHotRegionRectangle(rgn
, RectangleF
.Empty
, elementType
);
2845 list
.AddRange(this.GetMarkers(rect
, elementType
));
2849 PointF
[] points
= rgn
.Path
.PathPoints
;
2850 list
.AddRange(points
);
2856 LegendItem legendItem
= chartObject
as LegendItem
;
2857 if (legendItem
!= null)
2859 rect
= Rectangle
.Empty
;
2860 foreach (HotRegion rgn
in regions
)
2862 rect
= this.GetHotRegionRectangle(rgn
, rect
, elementType
);
2866 list
.AddRange(this.GetMarkers(rect
, elementType
));
2870 else if (chartObject
is Annotation
)
2872 rect
= Rectangle
.Empty
;
2873 foreach (HotRegion rgn
in regions
)
2875 rect
= this.GetHotRegionRectangle(rgn
, rect
, elementType
);
2879 list
.AddRange(this.GetMarkers(rect
, elementType
));
2883 foreach (HotRegion rgn
in regions
)
2885 rect
= this.GetHotRegionRectangle(rgn
, RectangleF
.Empty
, elementType
);
2886 list
.AddRange(this.GetMarkers(rect
, elementType
));
2894 /// Gets the markers.
2896 /// <param name="chartObject">The chart object.</param>
2897 /// <param name="elementType">Type of the element.</param>
2898 /// <returns></returns>
2899 private ArrayList
GetMarkers(object chartObject
, ChartElementType elementType
)
2901 ChartArea chartArea
= chartObject
as ChartArea
;
2902 if (chartArea
!= null)
2904 return this.GetAreaMarkers(this.Graph
, chartArea
);
2908 Axis axis
= chartObject
as Axis
;
2912 elementType
== ChartElementType
.AxisLabelImage
||
2913 elementType
== ChartElementType
.AxisLabels
||
2914 elementType
== ChartElementType
.AxisTitle
2917 return this.GetMarkersFromRegions(chartObject
, elementType
);
2919 return this.GetAxisMarkers(this.Graph
, axis
);
2922 DataPoint dataPoint
= chartObject
as DataPoint
;
2923 if (dataPoint
!= null)
2925 return this.GetMarkersFromRegions(chartObject
, elementType
);
2928 Series series
= chartObject
as Series
;
2931 if (elementType
== ChartElementType
.DataPointLabel
)
2933 return this.GetMarkersFromRegions(chartObject
, elementType
);
2935 return this.GetSeriesMarkers(series
);
2938 return this.GetMarkersFromRegions(chartObject
, elementType
);
2942 /// Determines whether specified chart area is circular or not have axes. These chart areas contain pie, doughnut, polar, radar
2944 /// <param name="area">The area.</param>
2946 /// <c>true</c> if specified chart area is circular; otherwise, <c>false</c>.
2948 private Boolean
IsChartAreaCircular(ChartArea area
)
2950 foreach (object o
in area
.ChartTypes
)
2952 ChartTypes
.IChartType chartType
= area
.Common
.ChartTypeRegistry
.GetChartType(o
.ToString());
2953 if (chartType
!= null && (chartType
.CircularChartArea
|| !chartType
.RequireAxes
))
2962 /// Determines whether the chart area is in 3D mode.
2964 /// <param name="area">The area.</param>
2966 /// <c>true</c> if the chart area is in 3D mode; otherwise, <c>false</c>.
2968 private Boolean
IsArea3D(ChartArea area
)
2970 return area
.Area3DStyle
.Enable3D
&& !this.IsChartAreaCircular(area
) && area
.matrix3D
!= null && area
.matrix3D
.IsInitialized();
2974 /// Gets the series markers.
2976 /// <param name="series">The series.</param>
2977 /// <returns>List of PointF.</returns>
2978 private ArrayList
GetSeriesMarkers(Series series
)
2980 ArrayList list
= new ArrayList();
2983 String areaName
= series
.ChartArea
;
2985 if (String
.IsNullOrEmpty(areaName
))
2987 areaName
= ChartPicture
.ChartAreas
.DefaultNameReference
;
2990 if (ChartPicture
.ChartAreas
.IndexOf(areaName
) != -1 && series
.Enabled
)
2993 ChartArea chartArea
= ChartPicture
.ChartAreas
[areaName
];
2995 if (ChartControl
.Series
.IndexOf(series
.Name
) != -1)
2997 series
= ChartControl
.Series
[series
.Name
];
3000 DataPointCollection points
= series
.Points
;
3001 // in design mode we have usually fake points
3002 if (points
.Count
== 0)
3004 points
= series
.fakeDataPoints
;
3006 // transform points in 3D
3007 foreach (DataPoint point
in points
)
3009 PointF pp
= this.Transform3D(chartArea
, point
);
3010 if (float.IsNaN(pp
.X
) || float.IsNaN(pp
.Y
))
3014 list
.Add(this.Graph
.GetAbsolutePoint(pp
));
3022 /// Gets the axis markers - list of points where markers are drawn.
3024 /// <param name="graph">The graph.</param>
3025 /// <param name="axis">The axis.</param>
3026 /// <returns>List of PointF.</returns>
3027 private ArrayList
GetAxisMarkers(ChartGraphics graph
, Axis axis
)
3029 ArrayList list
= new ArrayList();
3034 PointF first
= PointF
.Empty
;
3035 PointF second
= PointF
.Empty
;
3037 // Set the position of axis
3038 switch (axis
.AxisPosition
)
3041 case AxisPosition
.Left
:
3043 first
.X
= (float)axis
.GetAxisPosition();
3044 first
.Y
= axis
.PlotAreaPosition
.Y
;
3045 second
.X
= (float)axis
.GetAxisPosition();
3046 second
.Y
= axis
.PlotAreaPosition
.Bottom
;
3047 first
.X
-= axis
.labelSize
+ axis
.markSize
;
3050 case AxisPosition
.Right
:
3052 first
.X
= (float)axis
.GetAxisPosition();
3053 first
.Y
= axis
.PlotAreaPosition
.Y
;
3054 second
.X
= (float)axis
.GetAxisPosition();
3055 second
.Y
= axis
.PlotAreaPosition
.Bottom
;
3056 second
.X
+= axis
.labelSize
+ axis
.markSize
;
3059 case AxisPosition
.Bottom
:
3061 first
.X
= axis
.PlotAreaPosition
.X
;
3062 first
.Y
= (float)axis
.GetAxisPosition();
3063 second
.X
= axis
.PlotAreaPosition
.Right
;
3064 second
.Y
= (float)axis
.GetAxisPosition();
3065 second
.Y
+= axis
.labelSize
+ axis
.markSize
;
3068 case AxisPosition
.Top
:
3070 first
.X
= axis
.PlotAreaPosition
.X
;
3071 first
.Y
= (float)axis
.GetAxisPosition();
3072 second
.X
= axis
.PlotAreaPosition
.Right
;
3073 second
.Y
= (float)axis
.GetAxisPosition();
3074 first
.Y
-= axis
.labelSize
+ axis
.markSize
;
3078 // Update axis line position for circular area
3079 if (axis
.ChartArea
.chartAreaIsCurcular
)
3081 second
.Y
= axis
.PlotAreaPosition
.Y
+ axis
.PlotAreaPosition
.Height
/ 2f
;
3084 RectangleF rect1
= new RectangleF(first
.X
, first
.Y
, second
.X
- first
.X
, second
.Y
- first
.Y
);
3086 SizeF size
= graph
.GetRelativeSize(new SizeF(3, 3));
3087 if (axis
.AxisPosition
== AxisPosition
.Top
|| axis
.AxisPosition
== AxisPosition
.Bottom
)
3089 rect1
.Inflate(2, size
.Height
);
3093 rect1
.Inflate(size
.Width
, 2);
3095 IList list1
= this.GetMarkers(rect1
, ChartElementType
.Axis
);
3096 ChartArea area
= axis
.ChartArea
;
3097 if (this.IsArea3D(area
))
3100 Boolean axisOnEdge
= false;
3101 float zPositon
= axis
.GetMarksZPosition(out axisOnEdge
);
3103 // Transform coordinates
3104 Point3D
[] points
= new Point3D
[list1
.Count
];
3105 for (int i
= 0; i
< list1
.Count
; i
++)
3107 points
[i
] = new Point3D(((PointF
)list1
[i
]).X
, ((PointF
)list1
[i
]).Y
, zPositon
);
3109 axis
.ChartArea
.matrix3D
.TransformPoints(points
);
3110 for (int i
= 0; i
< list1
.Count
; i
++)
3112 list1
[i
] = points
[i
].PointF
;
3115 foreach (PointF p
in list1
)
3117 list
.Add(graph
.GetAbsolutePoint(p
));
3123 /// Gets the area markers.
3125 /// <param name="graph">The graph.</param>
3126 /// <param name="area">The area.</param>
3127 /// <returns>List of PointF.</returns>
3128 private ArrayList
GetAreaMarkers(ChartGraphics graph
, ChartArea area
)
3130 ArrayList list
= new ArrayList();
3135 IList list1
= this.GetMarkers(area
.PlotAreaPosition
.ToRectangleF(), ChartElementType
.PlottingArea
);
3136 if (this.IsChartAreaCircular(area
))
3138 list1
= this.GetMarkers(area
.lastAreaPosition
, ChartElementType
.PlottingArea
);
3142 float zPositon
= 0; // area.areaSceneDepth;
3143 // Transform coordinates
3144 Point3D
[] points
= new Point3D
[list1
.Count
];
3145 for (int i
= 0; i
< list1
.Count
; i
++)
3147 points
[i
] = new Point3D(((PointF
)list1
[i
]).X
, ((PointF
)list1
[i
]).Y
, zPositon
);
3149 area
.matrix3D
.TransformPoints(points
);
3150 for (int i
= 0; i
< list1
.Count
; i
++)
3152 list1
[i
] = points
[i
].PointF
;
3155 foreach (PointF p
in list1
)
3157 list
.Add(graph
.GetAbsolutePoint(p
));
3163 /// Builds list of markers (PointF) based on rectangle
3165 /// <param name="rect">The rectangle</param>
3166 /// <param name="elementType">The type of chart elements to retrieve.</param>
3167 /// <returns>List of PointF</returns>
3168 private ArrayList
GetMarkers(RectangleF rect
, ChartElementType elementType
)
3170 if (elementType
.ToString().StartsWith("Legend", StringComparison
.Ordinal
) || elementType
.ToString().StartsWith("Title", StringComparison
.Ordinal
))
3172 rect
.Inflate(4f
, 4f
);
3174 if (elementType
.ToString().StartsWith("PlottingArea", StringComparison
.Ordinal
))
3176 SizeF relSize
= this.Graph
.GetRelativeSize(new SizeF(4f
, 4f
));
3177 rect
.Inflate(relSize
.Width
, relSize
.Height
);
3180 if ((elementType
!= ChartElementType
.Nothing
) && (elementType
!= ChartElementType
.PlottingArea
))
3182 return this.GetMarkers(rect
, false);
3184 return this.GetMarkers(rect
, true);
3189 /// Builds list of markers (PointF) based on rectangle
3191 /// <param name="rect">The rectangle</param>
3192 /// <param name="addAdditionalMarkers">Add additional markers to the rectangle.</param>
3193 /// <returns>List of PointF</returns>
3194 private ArrayList
GetMarkers(RectangleF rect
, Boolean addAdditionalMarkers
)
3196 ArrayList list
= new ArrayList();
3197 if (!addAdditionalMarkers
)
3199 if (rect
.Width
> 0 && rect
.Height
> 0)
3201 list
.Add(new PointF(rect
.Left
, rect
.Top
));
3202 list
.Add(new PointF(rect
.Right
, rect
.Top
));
3203 list
.Add(new PointF(rect
.Right
, rect
.Bottom
));
3204 list
.Add(new PointF(rect
.Left
, rect
.Bottom
));
3206 else if (rect
.Width
> 0)
3208 list
.Add(new PointF(rect
.Left
, rect
.Top
));
3209 list
.Add(new PointF(rect
.Right
, rect
.Top
));
3211 else if (rect
.Height
> 0)
3213 list
.Add(new PointF(rect
.Left
, rect
.Top
));
3214 list
.Add(new PointF(rect
.Left
, rect
.Bottom
));
3221 list
.Add(new PointF(rect
.Left
, rect
.Top
));
3223 if (rect
.Width
> 30)
3225 list
.Add(new PointF(rect
.Left
+ rect
.Width
/ 2, rect
.Top
));
3228 list
.Add(new PointF(rect
.Right
, rect
.Top
));
3230 if (rect
.Height
> 30)
3232 list
.Add(new PointF(rect
.Right
, rect
.Top
+ rect
.Height
/ 2));
3235 list
.Add(new PointF(rect
.Right
, rect
.Bottom
));
3236 if (rect
.Width
> 30)
3238 list
.Add(new PointF(rect
.Left
+ rect
.Width
/ 2, rect
.Bottom
));
3241 list
.Add(new PointF(rect
.Left
, rect
.Bottom
));
3242 if (rect
.Height
> 30)
3244 list
.Add(new PointF(rect
.Left
, rect
.Top
+ rect
.Height
/ 2));
3248 else if (rect
.Width
> 0)
3250 list
.Add(new PointF(rect
.Left
, rect
.Top
));
3252 if (rect
.Width
> 30)
3254 list
.Add(new PointF(rect
.Left
+ rect
.Width
/ 2, rect
.Top
));
3257 list
.Add(new PointF(rect
.Right
, rect
.Top
));
3259 else if (rect
.Height
> 0)
3261 list
.Add(new PointF(rect
.Left
, rect
.Bottom
));
3262 if (rect
.Height
> 30)
3264 list
.Add(new PointF(rect
.Left
, rect
.Top
+ rect
.Height
/ 2));
3266 list
.Add(new PointF(rect
.Left
, rect
.Top
));
3273 /// Gets the region markers from graphics path.
3275 /// <param name="path">The path.</param>
3276 /// <returns>List of PointF.</returns>
3277 private ArrayList
GetRegionMarkers(GraphicsPath path
)
3279 return new ArrayList(path
.PathPoints
);
3283 /// Calculates a DataPoint of 3D area into PointF to draw.
3285 /// <param name="chartArea">3D chart area</param>
3286 /// <param name="point">The DataPoint</param>
3287 /// <returns>Calculated PointF</returns>
3288 private PointF
Transform3D(ChartArea chartArea
, DataPoint point
)
3290 if (chartArea
is ChartArea
&& IsArea3D(chartArea
))
3292 // Get anotation Z coordinate (use scene depth or anchored point Z position)
3293 float positionZ
= chartArea
.areaSceneDepth
;
3294 if (point
!= null && point
.series
!= null)
3297 chartArea
.GetSeriesZPositionAndDepth(
3301 positionZ
+= depth
/ 2f
;
3304 PointF pf
= point
.positionRel
;
3306 // Define 3D points of annotation object
3307 Point3D
[] annot3DPoints
= new Point3D
[1];
3308 annot3DPoints
[0] = new Point3D(pf
.X
, pf
.Y
, positionZ
);
3310 // Tranform cube coordinates
3311 chartArea
.matrix3D
.TransformPoints(annot3DPoints
);
3313 return annot3DPoints
[0].PointF
;
3315 return point
.positionRel
;
3319 /// Gets the hot region rectangle.
3321 /// <param name="rgn">The hot region.</param>
3322 /// <param name="unionWith">The rectangle to union with.</param>
3323 /// <param name="elementType">The type of the element.</param>
3324 /// <returns>Returns the rectangle around the hot region.</returns>
3325 private RectangleF
GetHotRegionRectangle(HotRegion rgn
, RectangleF unionWith
, ChartElementType elementType
)
3328 if (rgn
.Path
!= null)
3330 rect
= rgn
.Path
.GetBounds();
3334 rect
= rgn
.BoundingRectangle
;
3336 if (rgn
.RelativeCoordinates
)
3338 rect
= this.Graph
.GetAbsoluteRectangle(rect
);
3340 if (elementType
== ChartElementType
.AxisLabels
)
3342 if (rect
.Width
> rect
.Height
)
3344 rect
.Inflate(-5, -2);
3346 else if (rect
.Width
< rect
.Height
)
3348 rect
.Inflate(-2, -5);
3351 if (!unionWith
.IsEmpty
)
3353 return RectangleF
.Union(unionWith
, rect
);
3358 #endregion //Selection
3360 #endregion //Tooltips
3362 #region IServiceProvider Members
3365 /// Gets the service object of the specified type.
3367 /// <param name="serviceType">An object that specifies the type of service object to get.</param>
3369 /// A service object of type <paramref name="serviceType"/>. It returns null
3370 /// if there is no service object of type <paramref name="serviceType"/>.
3372 object IServiceProvider
.GetService(Type serviceType
)
3374 if (serviceType
== typeof(Selection
))
3378 if (_service
!= null)
3380 return _service
.GetService(serviceType
);
3390 #if Microsoft_CONTROL
3392 /// The ToolTipEventArgs class stores the tool tips event arguments.
3394 public class ToolTipEventArgs
: EventArgs
3396 #region Private fields
3398 // Private fields for properties values storage
3401 private string text
= "";
3402 private HitTestResult result
= new HitTestResult();
3406 #region Constructors
3409 /// ToolTipEventArgs constructor. Creates ToolTip event arguments.
3411 /// <param name="x">X-coordinate of mouse.</param>
3412 /// <param name="y">Y-coordinate of mouse.</param>
3413 /// <param name="text">Tooltip text.</param>
3414 /// <param name="result">Hit test result object.</param>
3415 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
3416 Justification
= "X and Y are cartesian coordinates and well understood")]
3417 public ToolTipEventArgs(int x
, int y
, string text
, HitTestResult result
)
3422 this.result
= result
;
3430 /// Gets the x-coordinate of the mouse.
3433 SRDescription("DescriptionAttributeToolTipEventArgs_X"),
3435 [System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId
= "X")]
3445 /// Gets the result of the hit test.
3448 SRDescription("DescriptionAttributeToolTipEventArgs_HitTestResult"),
3450 public HitTestResult HitTestResult
3459 /// Gets the y-coordinate of the mouse.
3462 SRDescription("DescriptionAttributeToolTipEventArgs_Y"),
3464 [System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId
= "Y")]
3474 /// Gets the text of the tooltip.
3477 SRDescription("DescriptionAttributeToolTipEventArgs_Text"),
3494 #endif // #if Microsoft_CONTROL