1 //-------------------------------------------------------------
2 // <copyright company=
\92Microsoft Corporation
\92>
3 // Copyright © Microsoft Corporation. All Rights Reserved.
5 //-------------------------------------------------------------
6 // @owner=alexgor, deliant
7 //=================================================================
8 // File: AxisScrollZoom.cs
10 // Namespace: System.Web.UI.WebControls[Windows.Forms].Charting
12 // Classes: AxisScaleView, ViewEventArgs, DoubleNanValueConverter
14 // Purpose: AxisScaleView class represents a data scaleView, and is
15 // exposed using the Axis.ScaleView property. A data scaleView is
16 // a "scaleView" of data that has a start position (represented
17 // by the Position property) and a size (represented by
18 // the Size property).
20 // Axis data scaleView is used in zooming and scrolling when
21 // only part of the data must be visible. Views always
22 // belong to an axis, and a scaleView can result from either
23 // user interaction or by calling the Zoom or Scroll
24 // methods. User interaction, accomplished using range
25 // selection along an axis using the mouse, is possible
26 // if the IsUserSelectionEnabled property of the chart area'
27 // s cursor property is set to true. The end-user selects
28 // a range by left-clicking the mouse and dragging the
29 // mouse, and when the mouse button is released the
30 // selected range is then displayed as a scaleView.
32 // Reviewed: AG - Microsoft 16, 2007
34 //===================================================================
36 #region Used namespace
40 using System.Drawing.Drawing2D;
41 using System.ComponentModel;
42 using System.Collections;
43 using System.Globalization;
46 using System.Windows.Forms.DataVisualization.Charting;
47 using System.Windows.Forms.DataVisualization.Charting.Data;
48 using System.Windows.Forms.DataVisualization.Charting.ChartTypes;
49 using System.Windows.Forms.DataVisualization.Charting.Utilities;
50 using System.Windows.Forms.DataVisualization.Charting.Borders3D;
51 using System.Diagnostics.CodeAnalysis;
55 using System.Web.UI.DataVisualization.Charting;
56 using System.Web.UI.DataVisualization.Charting.Utilities;
63 namespace System.Windows.Forms.DataVisualization.Charting
65 namespace System.Web.UI.DataVisualization.Charting
69 #region Scrolling enumerations
74 /// Scrolling type enumeration.
76 public enum ScrollType
79 /// Scrolls by substracting one small size.
83 /// Scrolls by adding one small size.
87 /// Scrolls by substracting one scaleView size.
91 /// Scrolls by adding one scaleView size.
95 /// Scrolls to the first scaleView.
99 /// Scrolls to the last scaleView.
104 #endif // Microsoft_CONTROL
109 /// AxisScaleView class represents a scale view which allows to display
110 /// only part of the available data.
113 SRDescription("DescriptionAttributeAxisDataView_AxisDataView"),
114 DefaultProperty("Position"),
117 [AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
118 [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
120 public class AxisScaleView
124 // Reference to the axis object
125 internal Axis axis = null;
127 // Axis data scaleView position
128 private double _position = double.NaN;
130 // Axis data scaleView size
131 private double _size = double.NaN;
133 // Axis data scaleView size units type
134 private DateTimeIntervalType _sizeType = DateTimeIntervalType.Auto;
136 #if Microsoft_CONTROL
138 // Axis data scaleView minimum scaleView/scrolling size
139 private double _minSize = double.NaN;
141 // Axis data scaleView minimum scaleView/scrolling size units type
142 private DateTimeIntervalType _minSizeType = DateTimeIntervalType.Auto;
144 // Axis data scaleView zooming UI interface enabled flag
145 private bool _zoomable = true;
147 // Axis data scaleView scroll line size
148 private double _smallScrollSize = double.NaN;
150 // Axis data scaleView scroll line size units type
151 private DateTimeIntervalType _smallScrollSizeType = DateTimeIntervalType.Auto;
153 // Axis data scaleView scroll line minimum size
154 private double _smallScrollMinSize = 1.0;
156 // Axis data scaleView scroll line minimum size units type
157 private DateTimeIntervalType _smallScrollMinSizeType = DateTimeIntervalType.Auto;
159 // Axis data scaleView scroll line minimum size
160 private double _currentSmallScrollSize = double.NaN;
162 // Axis data scaleView scroll line minimum size units type
163 private DateTimeIntervalType _currentSmallScrollSizeType = DateTimeIntervalType.Auto;
165 // Storage for the saved data scaleView states (position/size/sizetype)
166 internal ArrayList dataViewStates = null;
170 // Ignore validation flag
171 private bool _ignoreValidation = false;
178 /// Default constructor
180 public AxisScaleView()
186 /// Internal constructor.
188 /// <param name="axis">Data scaleView axis.</param>
189 internal AxisScaleView(Axis axis)
196 #region Axis data scaleView properties
199 /// Gets or sets the position of the AxisScaleView.
202 SRCategory("CategoryAttributeAxisView"),
204 DefaultValue(Double.NaN),
205 SRDescription("DescriptionAttributeAxisDataView_Position"),
206 TypeConverter(typeof(DoubleDateNanValueConverter)),
207 ParenthesizePropertyNameAttribute(true)
209 public double Position
213 // Axis scaleView is not supported in circular chrt areas
214 if(this.axis != null && this.axis.ChartArea != null && this.axis.ChartArea.chartAreaIsCurcular)
222 // Axis scaleView is not supported in circular chrt areas
223 if(this.axis != null && this.axis.ChartArea != null && this.axis.ChartArea.chartAreaIsCurcular)
228 if(_position != value)
233 // Align scaleView in connected areas
234 if(this.axis != null && this.axis.ChartArea != null && this.axis.Common != null && this.axis.Common.ChartPicture != null)
236 if(!this.axis.ChartArea.alignmentInProcess)
238 AreaAlignmentOrientations orientation = (this.axis.axisType == AxisName.X || this.axis.axisType== AxisName.X2) ?
239 AreaAlignmentOrientations.Vertical : AreaAlignmentOrientations.Horizontal;
240 this.axis.Common.ChartPicture.AlignChartAreasAxesView(this.axis.ChartArea, orientation);
245 if(!_ignoreValidation && axis != null)
254 /// Gets or sets the size of the AxisScaleView
257 SRCategory("CategoryAttributeAxisView"),
259 DefaultValue(Double.NaN),
260 SRDescription("DescriptionAttributeAxisDataView_Size"),
261 TypeConverter(typeof(DoubleNanValueConverter)),
262 ParenthesizePropertyNameAttribute(true)
268 // Axis scaleView is not supported in circular chrt areas
269 if(this.axis != null && this.axis.ChartArea != null && this.axis.ChartArea.chartAreaIsCurcular)
278 // Axis scaleView is not supported in circular chrt areas
279 if(this.axis != null && this.axis.ChartArea != null && this.axis.ChartArea.chartAreaIsCurcular)
290 // Align scaleView in connected areas
291 if(this.axis != null && this.axis.ChartArea != null && this.axis.Common != null && this.axis.Common.ChartPicture != null)
293 if(!this.axis.ChartArea.alignmentInProcess)
295 AreaAlignmentOrientations orientation = (this.axis.axisType == AxisName.X || this.axis.axisType== AxisName.X2) ?
296 AreaAlignmentOrientations.Vertical : AreaAlignmentOrientations.Horizontal;
297 this.axis.Common.ChartPicture.AlignChartAreasAxesView(this.axis.ChartArea, orientation);
300 #if Microsoft_CONTROL
301 // Reset current scrolling line size
302 this._currentSmallScrollSize = double.NaN;
303 #endif //Microsoft_CONTROL
305 if(!_ignoreValidation && axis != null)
314 /// Gets or sets the unit of measurement of the Size property.
317 SRCategory("CategoryAttributeAxisView"),
319 DefaultValue(DateTimeIntervalType.Auto),
320 SRDescription("DescriptionAttributeAxisDataView_SizeType"),
321 ParenthesizePropertyNameAttribute(true)
323 public DateTimeIntervalType SizeType
331 if(_sizeType != value)
334 _sizeType = (value != DateTimeIntervalType.NotSet) ? value : DateTimeIntervalType.Auto;
336 // Align scaleView in connected areas
337 if(this.axis != null && this.axis.ChartArea != null && this.axis.Common != null && this.axis.Common.ChartPicture != null)
339 if(!this.axis.ChartArea.alignmentInProcess)
341 AreaAlignmentOrientations orientation = (this.axis.axisType == AxisName.X || this.axis.axisType== AxisName.X2) ?
342 AreaAlignmentOrientations.Vertical : AreaAlignmentOrientations.Horizontal;
343 this.axis.Common.ChartPicture.AlignChartAreasAxesView(this.axis.ChartArea, orientation);
348 if(!_ignoreValidation && axis != null)
357 /// Indicates if axis is zoomed-in.
360 SRCategory("CategoryAttributeAxisView"),
363 SRDescription("DescriptionAttributeAxisDataView_IsZoomed"),
364 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
365 SerializationVisibility(SerializationVisibility.Hidden),
372 !double.IsNaN(this.Size) &&
374 !double.IsNaN(this.Position));
378 #if Microsoft_CONTROL
381 /// Gets or sets the minimum size of the AxisScaleView.
384 SRCategory("CategoryAttributeAxisView"),
386 DefaultValue(Double.NaN),
387 SRDescription("DescriptionAttributeAxisDataView_MinSize"),
388 TypeConverter(typeof(DoubleNanValueConverter))
390 public double MinSize
403 /// Gets or sets the unit of measurement of the MinSize property.
406 SRCategory("CategoryAttributeAxisView"),
408 DefaultValue(DateTimeIntervalType.Auto),
409 SRDescription("DescriptionAttributeAxisDataView_MinSizeType"),
411 public DateTimeIntervalType MinSizeType
419 _minSizeType = (value != DateTimeIntervalType.NotSet) ? value : DateTimeIntervalType.Auto;
424 /// Gets or sets a flag which indicates whether the zooming user interface is enabled.
427 SRCategory("CategoryAttributeAxisView"),
430 SRDescription("DescriptionAttributeAxisDataView_Zoomable"),
431 SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
432 Justification="'Zoomable' is a commonly used term and generally well understood"),
447 /// Gets or sets the small scrolling size.
450 SRCategory("CategoryAttributeAxisView"),
452 DefaultValue(Double.NaN),
453 SRDescription("DescriptionAttributeAxisDataView_SmallScrollSize"),
454 TypeConverter(typeof(AxisMinMaxAutoValueConverter))
456 public double SmallScrollSize
460 return _smallScrollSize;
464 if(_smallScrollSize != value)
467 _smallScrollSize = value;
470 if(!_ignoreValidation && axis != null)
479 /// Gets or sets the unit of measurement for the SmallScrollMinSize property
482 SRCategory("CategoryAttributeAxisView"),
484 DefaultValue(DateTimeIntervalType.Auto),
485 SRDescription("DescriptionAttributeAxisDataView_SmallScrollSizeType"),
487 public DateTimeIntervalType SmallScrollSizeType
491 return _smallScrollSizeType;
495 if(_smallScrollSizeType != value)
498 _smallScrollSizeType = (value != DateTimeIntervalType.NotSet) ? value : DateTimeIntervalType.Auto;
501 if(!_ignoreValidation && axis != null)
510 /// Gets or sets the minimum small scrolling size.
511 /// Only used if the small scrolling size is not set.
514 SRCategory("CategoryAttributeAxisView"),
517 SRDescription("DescriptionAttributeAxisDataView_SmallScrollMinSize")
519 public double SmallScrollMinSize
523 return _smallScrollMinSize;
527 if(_smallScrollMinSize != value)
530 _smallScrollMinSize = value;
532 _currentSmallScrollSize = double.NaN;
535 if(!_ignoreValidation && axis != null)
544 /// Gets or sets the unit of measurement for the SmallScrollMinSize property.
547 SRCategory("CategoryAttributeAxisView"),
549 DefaultValue(DateTimeIntervalType.Auto),
550 SRDescription("DescriptionAttributeAxisDataView_SmallScrollMinSizeType"),
552 public DateTimeIntervalType SmallScrollMinSizeType
556 return _smallScrollMinSizeType;
560 if(_smallScrollMinSizeType != value)
563 _smallScrollMinSizeType = (value != DateTimeIntervalType.NotSet) ? value : DateTimeIntervalType.Auto;
565 _currentSmallScrollSize = double.NaN;
568 if(!_ignoreValidation && axis != null)
576 #endif // Microsoft_CONTROL
580 #region ScaleView position internal methods
583 /// Call this method to get the minimum axis value of a data view.
585 /// <returns>The minimum axis value for the data view.</returns>
587 [Utilities.SerializationVisibility(Utilities.SerializationVisibility.Hidden)]
588 public double ViewMinimum
592 // If zooming is enabled
593 if (!Double.IsNaN(this.Size))
595 // If size set only use axis minimum for scaleView position
596 if (Double.IsNaN(this.Position))
598 this.Position = this.axis.Minimum;
600 // Check if scaleView position and size are set
603 // Calculate and add axis side margin
604 if (this.Position <= axis.minimum)
606 return this.Position;
608 else // Add a margin only if scaleView is inside data point scaleView
610 return this.Position - axis.marginView;
615 // Return axis scale minimum value if scaleView position is not set
621 /// Maximum axis value of a data view.
623 /// <returns>The maximum axis value for the data view.</returns>
625 [Utilities.SerializationVisibility(Utilities.SerializationVisibility.Hidden)]
626 public double ViewMaximum
630 // If zooming is enabled
631 if (!Double.IsNaN(this.Size))
633 // If size set only use axis minimum for scaleView position
634 if (Double.IsNaN(this.Position))
636 this.Position = this.axis.Minimum;
639 // Check if scaleView position and size are set
643 double viewSize = ChartHelper.GetIntervalSize(this.Position, this.Size, this.SizeType);
645 // Calculate and add axis side margin
646 if (this.Position + viewSize >= axis.maximum)
648 return this.Position + viewSize;
650 else // Add a margin only if scaleView is inside data point scaleView
652 return this.Position + viewSize + axis.marginView;
657 // Return axis scale maximum value if scaleView position is not set
664 #region Scrolling methods
666 #if Microsoft_CONTROL
669 /// Call this method to scroll to a specified position along an axis.
671 /// <param name="scrollType">Direction and size to scroll.</param>
672 public void Scroll(ScrollType scrollType)
674 this.Scroll(scrollType, false);
678 /// Scrolls axis data scaleView from current position.
680 /// <param name="scrollType">Direction and size to scroll.</param>
681 /// <param name="fireChangeEvents">Fire scaleView position events from this method.</param>
682 internal void Scroll(ScrollType scrollType, bool fireChangeEvents)
684 // Adjust current position depending on the scroll type
685 double newPosition = this._position;
688 case(ScrollType.SmallIncrement):
689 newPosition += ((axis.IsReversed) ? -1 : 1) * ChartHelper.GetIntervalSize(this._position, this.GetScrollingLineSize(), this.GetScrollingLineSizeType());
691 case(ScrollType.SmallDecrement):
692 newPosition -= ((axis.IsReversed) ? -1 : 1) * ChartHelper.GetIntervalSize(this._position, this.GetScrollingLineSize(), this.GetScrollingLineSizeType());
694 case(ScrollType.LargeIncrement):
695 newPosition += ((axis.IsReversed) ? -1 : 1) * ChartHelper.GetIntervalSize(this._position, this.Size, this.SizeType);
697 case(ScrollType.LargeDecrement):
698 newPosition -= ((axis.IsReversed) ? -1 : 1) * ChartHelper.GetIntervalSize(this._position, this.Size, this.SizeType);
700 case(ScrollType.First):
703 newPosition = (axis.minimum + axis.marginView);
707 newPosition = (axis.maximum - axis.marginView);
710 case(ScrollType.Last):
712 double viewSize = ChartHelper.GetIntervalSize(newPosition, this.Size, this.SizeType);
715 newPosition = (axis.maximum - axis.marginView - viewSize);
719 newPosition = (axis.minimum + axis.marginView + viewSize);
725 // Scroll to the new position
726 this.Scroll(newPosition, fireChangeEvents);
730 /// Call this method to scroll to a specified position along an axis.
732 /// <param name="newPosition">New position.</param>
733 public void Scroll(double newPosition)
735 this.Scroll(newPosition, false);
739 /// Call this method to scroll to a specified position along an axis.
741 /// <param name="newPosition">New position.</param>
742 public void Scroll(DateTime newPosition)
744 this.Scroll(newPosition.ToOADate(), false);
748 /// Internal helper method for scrolling into specified position.
750 /// <param name="newPosition">New data scaleView position.</param>
751 /// <param name="fireChangeEvents">Fire scaleView position events from this method.</param>
752 internal void Scroll(double newPosition, bool fireChangeEvents)
754 // Get current scaleView size
755 double viewSize = ChartHelper.GetIntervalSize(newPosition, this.Size, this.SizeType);
757 // Validate new scaleView position
758 if(newPosition < (axis.minimum + axis.marginView))
760 newPosition = (axis.minimum + axis.marginView);
762 else if(newPosition > (axis.maximum - axis.marginView - viewSize))
764 newPosition = (axis.maximum - axis.marginView - viewSize);
767 // Fire scaleView position changing events
768 ViewEventArgs arguments = new ViewEventArgs(this.axis, newPosition, this.Size, this.SizeType);
769 if(fireChangeEvents && GetChartObject() != null)
771 GetChartObject().OnAxisViewChanging(arguments);
772 newPosition = arguments.NewPosition;
775 // Check if data scaleView position and size is different from current
776 if(newPosition == this.Position)
781 // Change scaleView position
782 this.Position = newPosition;
784 // Fire scaleView position changed events
785 if(fireChangeEvents && GetChartObject() != null)
787 GetChartObject().OnAxisViewChanged(arguments);
794 #region Zooming and ZoomResetting methods
796 #if Microsoft_CONTROL
799 /// Sets a new axis data view/position based on the start and end dates specified.
801 /// <param name="viewPosition">New start position for the axis scale view.</param>
802 /// <param name="viewSize">New size for the axis scale view.</param>
803 /// <param name="viewSizeType">New unit of measurement of the size.</param>
804 /// <param name="saveState">Indicates whether the current size/position needs to be saved.</param>
805 public void Zoom(double viewPosition, double viewSize, DateTimeIntervalType viewSizeType, bool saveState)
807 this.Zoom(viewPosition, viewSize, viewSizeType, false, saveState);
811 /// Sets a new axis data view/position based on the specified start and end values.
813 /// <param name="viewStart">New start position for the axis scale view.</param>
814 /// <param name="viewEnd">New end position for the axis scale view.</param>
815 public void Zoom(double viewStart, double viewEnd)
817 this.Zoom(viewStart, viewEnd - viewStart, DateTimeIntervalType.Number, false, false);
821 /// Sets a new axis data view/position based on the start and end dates specified.
823 /// <param name="viewPosition">New start position for the axis scale view.</param>
824 /// <param name="viewSize">New size for the axis scale view.</param>
825 /// <param name="viewSizeType">New unit of measurement of the size.</param>
826 public void Zoom(double viewPosition, double viewSize, DateTimeIntervalType viewSizeType)
828 this.Zoom(viewPosition, viewSize, viewSizeType, false, false);
832 /// Reset the specified number of zooming operations by restoring axis data view.
834 /// <param name="numberOfViews">Number of zoom operations to reset. Zero for all.</param>
835 public void ZoomReset(int numberOfViews)
837 this.LoadDataViewState(numberOfViews, false);
841 /// Reset one zooming operation by restoring axis data view.
843 public void ZoomReset()
845 this.LoadDataViewState(1, false);
849 /// Reset several zooming operation by restoring data scaleView size/position.
851 /// <param name="numberOfViews">How many scaleView zoom operations to reset. Zero for all.</param>
852 /// <param name="fireChangeEvents">Fire scaleView position events from this method.</param>
853 internal void ZoomReset(int numberOfViews, bool fireChangeEvents)
855 this.LoadDataViewState(numberOfViews, fireChangeEvents);
859 /// Internal helper zooming method.
861 /// <param name="viewPosition">New data scaleView start posiion.</param>
862 /// <param name="viewSize">New data scaleView size.</param>
863 /// <param name="viewSizeType">New data scaleView size units type.</param>
864 /// <param name="fireChangeEvents">Fire scaleView position events from this method.</param>
865 /// <param name="saveState">Indicates that current scaleView size/position must be save, so it can be restored later.</param>
866 /// <returns>True if zoom operation was made.</returns>
870 DateTimeIntervalType viewSizeType,
871 bool fireChangeEvents,
874 // Validate new scaleView position and size
875 ValidateViewPositionSize(ref viewPosition, ref viewSize, ref viewSizeType);
877 // Fire scaleView position/size changing events
878 ViewEventArgs arguments = new ViewEventArgs(this.axis, viewPosition, viewSize, viewSizeType);
879 if(fireChangeEvents && GetChartObject() != null)
881 GetChartObject().OnAxisViewChanging(arguments);
882 viewPosition = arguments.NewPosition;
883 viewSize = arguments.NewSize;
884 viewSizeType = arguments.NewSizeType;
887 // Check if data scaleView position and size is different from current
888 if(viewPosition == this.Position &&
889 viewSize == this.Size &&
890 viewSizeType == this.SizeType)
895 // Save current data scaleView state, so it can be restored
901 // Change scaleView position/size
902 this._ignoreValidation = true;
903 this.Position = viewPosition;
904 this.Size = viewSize;
905 this.SizeType = viewSizeType;
906 this._ignoreValidation = false;
908 // Reset current scrolling line size
909 this._currentSmallScrollSize = double.NaN;
914 // Fire scaleView position/size changed events
915 if(fireChangeEvents && GetChartObject() != null)
917 GetChartObject().OnAxisViewChanged(arguments);
927 #region Data scaleView state saving/restoring methods
929 #if Microsoft_CONTROL
932 /// Saves current data scaleView position/size/sizetype, so
933 /// it can be restored later.
935 /// <param name="numberOfViews">Number of time to reset zoom. Zero for all.</param>
936 /// <param name="fireChangeEvents">Fire scaleView position events from this method.</param>
937 private void LoadDataViewState(int numberOfViews, bool fireChangeEvents)
940 if(numberOfViews < 0)
942 throw (new ArgumentOutOfRangeException("numberOfViews", SR.ExceptionScrollBarZoomResetsNumberInvalid));
944 // Check if storage was created
945 if(dataViewStates != null && dataViewStates.Count >= 3)
947 // Find starting index of restoring state
948 int dataStartIndex = 0;
949 if(numberOfViews > 0)
951 dataStartIndex = dataViewStates.Count - numberOfViews * 3;
952 if(dataStartIndex < 0)
959 // Fire scaleView position/size changing events
960 ViewEventArgs arguments = new ViewEventArgs(
962 (double)dataViewStates[dataStartIndex],
963 (double)dataViewStates[dataStartIndex + 1],
964 (DateTimeIntervalType)dataViewStates[dataStartIndex + 2]);
965 if(fireChangeEvents && GetChartObject() != null)
967 GetChartObject().OnAxisViewChanging(arguments);
971 this.Position = arguments.NewPosition;
972 this.Size = arguments.NewSize;
973 this.SizeType = arguments.NewSizeType;
975 // Fire scaleView position/size changed events
976 if(fireChangeEvents && GetChartObject() != null)
978 GetChartObject().OnAxisViewChanged(arguments);
982 int itemsToRemove = numberOfViews * 3;
983 if (itemsToRemove > (dataViewStates.Count - dataStartIndex))
985 itemsToRemove = dataViewStates.Count - dataStartIndex;
987 dataViewStates.RemoveRange(dataStartIndex, itemsToRemove);
990 // clean up the history state when the numberOfViews == 0 (reset all by docs)
991 if ( numberOfViews == 0 )
993 dataViewStates.Clear();
995 if (Double.IsNaN(this.Position) || Double.IsNaN(this.Size))
997 this.Position = Double.NaN;
998 this.Size = Double.NaN;
1003 // Nothing to restore - just disable the data scaleView
1006 // Fire scaleView position/size changing events
1007 ViewEventArgs arguments = new ViewEventArgs(
1011 DateTimeIntervalType.Auto);
1013 if(fireChangeEvents && GetChartObject() != null)
1015 GetChartObject().OnAxisViewChanging(arguments);
1019 this.Position = arguments.NewPosition;
1020 this.Size = arguments.NewSize;
1021 this.SizeType = arguments.NewSizeType;
1023 // Fire scaleView position/size changed events
1024 if(fireChangeEvents && GetChartObject() != null)
1026 GetChartObject().OnAxisViewChanged(arguments);
1029 // clear cached chart areas and bitmap buffers
1030 GetChartObject().Refresh();
1034 /// Saves current data scaleView position/size/sizetype, so
1035 /// it can be restored later.
1037 private void SaveDataViewState()
1039 // Create storage array
1040 if(dataViewStates == null)
1042 dataViewStates = new ArrayList();
1045 // Save data scaleView state
1046 dataViewStates.Add(this.Position);
1047 dataViewStates.Add(this.Size);
1048 dataViewStates.Add(this.SizeType);
1054 #region Helper methods
1056 #if Microsoft_CONTROL
1058 /// Initialize internal scrolling line size variables for later use.
1059 /// This size is used in to scroll chart one line up or down.
1061 private void GetCurrentViewSmallScrollSize()
1063 //**************************************************************************
1064 //** Check if current scrolling line size was not already calculated
1065 //**************************************************************************
1066 if(double.IsNaN(_currentSmallScrollSize))
1068 //**************************************************************************
1069 //** Calculate line size depending on the current scaleView size
1070 //**************************************************************************
1071 if(this.SizeType == DateTimeIntervalType.Auto || this.SizeType == DateTimeIntervalType.Number)
1073 // Set line size type
1074 _currentSmallScrollSizeType = DateTimeIntervalType.Number;
1076 // Devide scaleView by 20 to find the scrolling line size
1077 double newSize = this.Size / 20.0;
1079 // Make sure that current line size is even with minimum value
1080 if(!double.IsNaN(this.SmallScrollMinSize) && this.SmallScrollMinSize != 0.0)
1082 double rounder = (Math.Round(newSize / this.SmallScrollMinSize));
1087 newSize = rounder * this.SmallScrollMinSize;
1090 // Set new current line size
1091 this._currentSmallScrollSize = newSize;
1095 // Calculate line size for date/time
1096 double viewEndPosition = this.Position + ChartHelper.GetIntervalSize(this.Position, this.Size, this.SizeType);
1097 _currentSmallScrollSize = axis.CalcInterval(
1101 out _currentSmallScrollSizeType,
1102 ChartValueType.Auto);
1105 //**************************************************************************
1106 //** Make sure calculated scroll line size is not smaller than the minimum
1107 //**************************************************************************
1108 if(!double.IsNaN(this.SmallScrollMinSize) && this.SmallScrollMinSize != 0.0)
1110 double newLineSize = ChartHelper.GetIntervalSize(this.Position, _currentSmallScrollSize, _currentSmallScrollSizeType);
1111 double minLineSize = ChartHelper.GetIntervalSize(this.Position, this.SmallScrollMinSize, this.SmallScrollMinSizeType);
1112 if(newLineSize < minLineSize)
1114 _currentSmallScrollSize = SmallScrollMinSize;
1115 _currentSmallScrollSizeType = SmallScrollMinSizeType;
1122 /// Returns the scroll line size.
1124 /// <returns>Scroll line size.</returns>
1125 internal double GetScrollingLineSize()
1127 // Scroll line size/type is specificly set by user
1128 if(!double.IsNaN(this.SmallScrollSize))
1130 return this.SmallScrollSize;
1133 // Calcualte scroll line size depending on the current scaleView size
1134 GetCurrentViewSmallScrollSize();
1137 return _currentSmallScrollSize;
1141 /// Returns the scroll line size units type.
1143 /// <returns>Scroll line size units type.</returns>
1144 internal DateTimeIntervalType GetScrollingLineSizeType()
1146 // Scroll line size/type is specificly set by user
1147 if(!double.IsNaN(this.SmallScrollSize))
1149 return this.SmallScrollSizeType;
1152 // Calcualte scroll line size depending on the current scaleView size
1153 GetCurrentViewSmallScrollSize();
1155 // Return line size units type
1156 return _currentSmallScrollSizeType;
1160 /// Helper method, which validates the axis data scaleView position and size.
1161 /// Returns adjusted scaleView position and size.
1163 /// <param name="viewPosition">ScaleView position.</param>
1164 /// <param name="viewSize">ScaleView size.</param>
1165 /// <param name="viewSizeType">ScaleView size units type.</param>
1166 private void ValidateViewPositionSize(ref double viewPosition, ref double viewSize, ref DateTimeIntervalType viewSizeType)
1168 //****************************************************************
1169 //** Check if new scaleView position is inside axis scale
1170 //** minimum/maximum without margin.
1171 //****************************************************************
1172 if(viewPosition < (axis.minimum + axis.marginView))
1174 if(viewSizeType == DateTimeIntervalType.Auto || viewSizeType == DateTimeIntervalType.Number)
1176 viewSize -= (axis.minimum + axis.marginView) - viewPosition;
1178 viewPosition = (axis.minimum + axis.marginView);
1180 else if(viewPosition > (axis.maximum - axis.marginView))
1182 if(viewSizeType == DateTimeIntervalType.Auto || viewSizeType == DateTimeIntervalType.Number)
1184 viewSize -= viewPosition - (axis.maximum - axis.marginView);
1186 viewPosition = (axis.maximum - axis.marginView);
1189 //****************************************************************
1190 //** Check if new scaleView size is not smaller than minimum size
1191 //** set by the user
1192 //****************************************************************
1193 double newViewSize = ChartHelper.GetIntervalSize(viewPosition, viewSize, viewSizeType);
1194 double minViewSize = ChartHelper.GetIntervalSize(viewPosition, 1, this.MinSizeType);
1195 if(!double.IsNaN(this.MinSize))
1197 minViewSize = ChartHelper.GetIntervalSize(viewPosition, this.MinSize, this.MinSizeType);
1198 if(newViewSize < minViewSize)
1200 viewSize = (double.IsNaN(this.MinSize)) ? 1 : this.MinSize;
1201 viewSizeType = this.MinSizeType;
1202 newViewSize = ChartHelper.GetIntervalSize(viewPosition, viewSize, viewSizeType);
1206 //****************************************************************
1207 //** Check if new scaleView size is smaller than (0.000000001)
1208 //****************************************************************
1209 if(newViewSize < 0.000000001)
1211 viewSize = 0.000000001;
1212 viewSizeType = DateTimeIntervalType.Number;
1213 newViewSize = ChartHelper.GetIntervalSize(viewPosition, viewSize, viewSizeType);
1216 //****************************************************************
1217 //** Check if new scaleView end position (position + size) is inside
1218 //** axis scale minimum/maximum without margin.
1219 //****************************************************************
1220 while( (viewPosition + newViewSize) > (axis.maximum - axis.marginView) )
1222 double currentSize = viewSize;
1223 DateTimeIntervalType currentSizeType = viewSizeType;
1225 // Try to reduce the scaleView size
1226 if(newViewSize > minViewSize)
1228 // Try to adjust the scaleView size
1233 else if(viewSizeType == DateTimeIntervalType.Years)
1236 viewSizeType = DateTimeIntervalType.Months;
1238 else if(viewSizeType == DateTimeIntervalType.Months)
1241 viewSizeType = DateTimeIntervalType.Weeks;
1243 else if(viewSizeType == DateTimeIntervalType.Weeks)
1246 viewSizeType = DateTimeIntervalType.Days;
1248 else if(viewSizeType == DateTimeIntervalType.Days)
1251 viewSizeType = DateTimeIntervalType.Hours;
1253 else if(viewSizeType == DateTimeIntervalType.Hours)
1256 viewSizeType = DateTimeIntervalType.Minutes;
1258 else if(viewSizeType == DateTimeIntervalType.Minutes)
1261 viewSizeType = DateTimeIntervalType.Seconds;
1263 else if(viewSizeType == DateTimeIntervalType.Seconds)
1266 viewSizeType = DateTimeIntervalType.Milliseconds;
1270 viewPosition = (axis.maximum - axis.marginView) - minViewSize;
1274 // Double check that scaleView size is not smaller than min size
1275 newViewSize = ChartHelper.GetIntervalSize(viewPosition, viewSize, viewSizeType);
1276 if(newViewSize < minViewSize)
1278 // Can't adjust size no more (restore prev. value)
1279 viewSize = currentSize;
1280 viewSizeType = currentSizeType;
1282 // Adjust the start position
1283 viewPosition = (axis.maximum - axis.marginView) - minViewSize;
1289 // Adjust the start position
1290 viewPosition = (axis.maximum - axis.marginView) - newViewSize;
1297 /// Helper function which returns a reference to the chart object.
1299 /// <returns>Chart object reference.</returns>
1300 internal Chart GetChartObject()
1302 if(this.axis != null && this.axis.Common!=null)
1304 return this.axis.Common.Chart;
1309 #endif //Microsoft_CONTROL
1314 #if Microsoft_CONTROL
1317 /// This class is used as a parameter object in the AxisViewChanged and AxisViewChanging events of the root Chart object.
1319 public class ViewEventArgs : EventArgs
1321 #region Private fields
1323 // Private fields for properties values storage
1324 private Axis _axis = null;
1325 private double _newPosition = double.NaN;
1326 private double _newSize = double.NaN;
1327 private DateTimeIntervalType _newSizeType = DateTimeIntervalType.Auto;
1331 #region Constructors
1334 /// ViewEventArgs constructor.
1336 /// <param name="axis">Axis of the scale view.</param>
1337 /// <param name="newPosition">New scale view start position.</param>
1338 public ViewEventArgs(Axis axis, double newPosition)
1341 this._newPosition = newPosition;
1345 /// ViewEventArgs constructor.
1347 /// <param name="axis">Axis of the scale view.</param>
1348 /// <param name="newPosition">New scale view start position.</param>
1349 /// <param name="newSize">New scale view size.</param>
1350 /// <param name="newSizeType">New unit of measurement of the size.</param>
1351 public ViewEventArgs(Axis axis, double newPosition, double newSize, DateTimeIntervalType newSizeType)
1354 this._newPosition = newPosition;
1355 this._newSize = newSize;
1356 this._newSizeType = newSizeType;
1364 /// Axis of the event.
1367 SRDescription("DescriptionAttributeAxis"),
1378 /// ChartArea of the event.
1381 SRDescription("DescriptionAttributeChartArea"),
1383 public ChartArea ChartArea
1387 return _axis.ChartArea;
1392 /// New scale view start position.
1395 SRDescription("DescriptionAttributeViewEventArgs_NewPosition"),
1397 public double NewPosition
1401 return _newPosition;
1405 _newPosition = value;
1410 /// New scale view size.
1413 SRDescription("DescriptionAttributeViewEventArgs_NewSize"),
1415 public double NewSize
1428 /// New unit of measurement of the scale view.
1431 SRDescription("DescriptionAttributeViewEventArgs_NewSizeType"),
1433 public DateTimeIntervalType NewSizeType
1437 return _newSizeType;
1441 _newSizeType = (value != DateTimeIntervalType.NotSet) ? value : DateTimeIntervalType.Auto;
1448 #endif // #if Microsoft_CONTROL
1451 #if Microsoft_CONTROL
1452 namespace System.Windows.Forms.DataVisualization.Charting
1454 namespace System.Web.UI.DataVisualization.Charting
1458 /// Designer converter class
1459 /// Converts Double.NaN values to/from "Not set".
1461 internal class DoubleNanValueConverter : DoubleConverter
1463 #region Converter methods
1466 /// Standard values supported. This method always return true.
1468 /// <param name="context">Descriptor context.</param>
1469 /// <returns>True.</returns>
1470 public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
1476 /// Standard values are not exclusive. This method always return false.
1478 /// <param name="context">Descriptor context.</param>
1479 /// <returns>False.</returns>
1480 public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
1486 /// Get in the collection of standard values.
1488 /// <param name="context">Descriptor context.</param>
1489 public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
1491 ArrayList values = new ArrayList();
1492 values.Add(Double.NaN);
1494 return new StandardValuesCollection(values);
1498 /// Convert double.NaN to string "Not set"
1500 /// <param name="context">Descriptor context.</param>
1501 /// <param name="culture">Culture information.</param>
1502 /// <param name="value">Value to convert.</param>
1503 /// <param name="destinationType">Conversion destination type.</param>
1504 /// <returns>Converted object.</returns>
1505 public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
1507 double doubleValue = (double)value;
1508 if (destinationType == typeof(string))
1510 if(Double.IsNaN(doubleValue))
1512 return Constants.NotSetValue;
1517 return base.ConvertTo(context, culture, value, destinationType);
1521 /// Convert minimum or maximum values from string.
1523 public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
1525 // If converting from string value
1526 string crossingValue = value as string;
1527 if (crossingValue != null)
1529 if (String.Compare(crossingValue, Constants.NotSetValue, StringComparison.OrdinalIgnoreCase) == 0)
1535 // Call base converter
1536 return base.ConvertFrom(context, culture, value);
1543 /// Designer converter class
1544 /// Converts Double.NaN values to/from "Not set".
1545 /// Converts value to/from date strings.
1547 internal class DoubleDateNanValueConverter : DoubleConverter
1549 #region Converter methods
1552 /// Standard values supported - return true
1554 /// <param name="context">Descriptor context.</param>
1555 /// <returns>Standard values supported.</returns>
1556 public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
1562 /// Standard values are not exclusive - return false
1564 /// <param name="context">Descriptor context.</param>
1565 /// <returns>Non exclusive standard values.</returns>
1566 public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
1572 /// Fill in the list of predefined values.
1574 /// <param name="context">Descriptor context.</param>
1575 public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
1577 ArrayList values = new ArrayList();
1578 values.Add(Double.NaN);
1580 return new StandardValuesCollection(values);
1584 /// Convert values to string if step type is set to one of the DateTime type
1586 /// <param name="context">Descriptor context.</param>
1587 /// <param name="culture">Culture information.</param>
1588 /// <param name="value">Value to convert.</param>
1589 /// <param name="destinationType">Conversion destination type.</param>
1590 /// <returns>Converted object.</returns>
1591 public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
1594 if (destinationType == typeof(string))
1596 if(Double.IsNaN((double)value))
1598 return Constants.NotSetValue;
1602 if (context != null && context.Instance != null)
1604 // Get access to the Axis object
1606 if(context.Instance is AxisScaleView)
1608 axis = ((AxisScaleView)context.Instance).axis;
1611 #if Microsoft_CONTROL
1613 else if(context.Instance is Cursor)
1615 axis = ((Cursor)context.Instance).GetAxis();
1617 #endif // Microsoft_CONTROL
1619 if (axis != null && destinationType == typeof(string))
1621 string strValue = ConvertDateTimeToString(
1623 axis.GetAxisValuesType(),
1624 axis.InternalIntervalType);
1626 if (strValue != null)
1631 return base.ConvertTo(context, culture, value, destinationType);
1634 public static string ConvertDateTimeToString(
1636 ChartValueType axisValuesType,
1637 DateTimeIntervalType dtIntervalType)
1639 string strValue = null;
1640 // Use axis values types if interval is automatic
1641 if (dtIntervalType == DateTimeIntervalType.Auto)
1643 if (axisValuesType == ChartValueType.DateTime ||
1644 axisValuesType == ChartValueType.Time ||
1645 axisValuesType == ChartValueType.Date ||
1646 axisValuesType == ChartValueType.DateTimeOffset)
1648 strValue = DateTime.FromOADate(dtValue).ToString("g", System.Globalization.CultureInfo.CurrentCulture);
1653 if (dtIntervalType != DateTimeIntervalType.Number)
1655 // Covert value to date/time
1656 if (dtIntervalType < DateTimeIntervalType.Hours)
1658 strValue = DateTime.FromOADate(dtValue).ToShortDateString();
1662 strValue = DateTime.FromOADate(dtValue).ToString("g", System.Globalization.CultureInfo.CurrentCulture);
1667 if (axisValuesType == ChartValueType.DateTimeOffset && strValue != null)
1674 /// Convert Min and Max values from string if step type is set to one of the DateTime type
1676 /// <param name="context">Descriptor context.</param>
1677 /// <param name="culture">Culture information.</param>
1678 /// <param name="value">Value to convert from.</param>
1679 /// <returns>Converted object.</returns>
1680 public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
1682 object result = null;
1683 bool convertFromDate = false;
1685 // If converting from string value
1686 string crossingValue = value as string;
1687 if (crossingValue != null)
1689 if (String.Compare(crossingValue, Constants.NotSetValue, StringComparison.OrdinalIgnoreCase) == 0)
1695 // If context interface provided check if we are dealing with DateTime values
1696 if (context != null && context.Instance != null && context.Instance is Axis)
1701 if(context.Instance is AxisScaleView)
1703 axis = ((AxisScaleView)context.Instance).axis;
1706 #if Microsoft_CONTROL
1707 else if(context.Instance is Cursor)
1709 axis = ((Cursor)context.Instance).GetAxis();
1711 #endif // Microsoft_CONTROL
1713 if (axis != null && crossingValue != null)
1715 if(axis.InternalIntervalType == DateTimeIntervalType.Auto)
1717 if(axis.GetAxisValuesType() == ChartValueType.DateTime ||
1718 axis.GetAxisValuesType() == ChartValueType.Date ||
1719 axis.GetAxisValuesType() == ChartValueType.Time ||
1720 axis.GetAxisValuesType() == ChartValueType.DateTimeOffset)
1722 convertFromDate = true;
1727 if(axis.InternalIntervalType != DateTimeIntervalType.Number)
1729 convertFromDate = true;
1735 // Try to convert from double string
1738 result = base.ConvertFrom(context, culture, value);
1740 catch (ArgumentException)
1744 catch (NotSupportedException)
1749 // Try to convert from date/time string
1750 if (crossingValue != null && (convertFromDate || result == null))
1752 DateTime valueAsDate;
1753 bool parseSucceed = DateTime.TryParse(crossingValue, CultureInfo.InvariantCulture, DateTimeStyles.None, out valueAsDate);
1757 return valueAsDate.ToOADate();
1761 // Call base converter
1762 return base.ConvertFrom(context, culture, value);