1 //-------------------------------------------------------------
2 // <copyright company=�Microsoft Corporation�>
3 //   Copyright � Microsoft Corporation. All Rights Reserved.
4 // </copyright>
5 //-------------------------------------------------------------
6 // @owner=alexgor, deliant
7 //=================================================================
8 //  File:		AxisScrollZoom.cs
9 //
10 //  Namespace:	System.Web.UI.WebControls[Windows.Forms].Charting
11 //
12 //	Classes:	AxisScaleView, ViewEventArgs, DoubleNanValueConverter
13 //
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).
19 //
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.
31 //
32 //	Reviewed:	AG - Microsoft 16, 2007
33 //
34 //===================================================================
35 
36 #region Used namespace
37 
38 using System;
39 using System.Drawing;
40 using System.Drawing.Drawing2D;
41 using System.ComponentModel;
42 using System.Collections;
43 using System.Globalization;
44 
45 #if Microsoft_CONTROL
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;
52 
53 
54 #else
55 	using System.Web.UI.DataVisualization.Charting;
56 	using System.Web.UI.DataVisualization.Charting.Utilities;
57 #endif
58 
59 
60 #endregion
61 
62 #if Microsoft_CONTROL
63 namespace System.Windows.Forms.DataVisualization.Charting
64 #else
65 namespace System.Web.UI.DataVisualization.Charting
66 #endif
67 {
68 
69     #region Scrolling  enumerations
70 
71 #if Microsoft_CONTROL
72 
73     /// <summary>
74 	/// Scrolling type enumeration.
75 	/// </summary>
76     public enum ScrollType
77 	{
78 		/// <summary>
79 		/// Scrolls by substracting one small size.
80 		/// </summary>
81 		SmallDecrement,
82 		/// <summary>
83 		/// Scrolls by adding one small size.
84 		/// </summary>
85 		SmallIncrement,
86 		/// <summary>
87 		/// Scrolls by substracting one scaleView size.
88 		/// </summary>
89 		LargeDecrement,
90 		/// <summary>
91 		/// Scrolls by adding one scaleView size.
92 		/// </summary>
93 		LargeIncrement,
94 		/// <summary>
95 		/// Scrolls to the first scaleView.
96 		/// </summary>
97 		First,
98 		/// <summary>
99 		/// Scrolls to the last scaleView.
100 		/// </summary>
101 		Last
102 	}
103 
104 #endif // Microsoft_CONTROL
105 
106 	#endregion
107 
108     /// <summary>
109     /// AxisScaleView class represents a scale view which allows to display
110     /// only part of the available data.
111     /// </summary>
112 	[
113 		SRDescription("DescriptionAttributeAxisDataView_AxisDataView"),
114 		DefaultProperty("Position"),
115 	]
116 #if ASPPERM_35
117 	[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
118     [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
119 #endif
120     public class AxisScaleView
121 	{
122 		#region Fields
123 
124 		// Reference to the axis object
125 		internal Axis					axis = null;
126 
127 		// Axis data scaleView position
128 		private	double					_position = double.NaN;
129 
130 		// Axis data scaleView size
131 		private	double					_size = double.NaN;
132 
133 		// Axis data scaleView size units type
134 		private	DateTimeIntervalType	_sizeType = DateTimeIntervalType.Auto;
135 
136 #if Microsoft_CONTROL
137 
138         // Axis data scaleView minimum scaleView/scrolling size
139 		private	double					_minSize = double.NaN;
140 
141 		// Axis data scaleView minimum scaleView/scrolling size units type
142 		private	DateTimeIntervalType	_minSizeType = DateTimeIntervalType.Auto;
143 
144 		// Axis data scaleView zooming UI interface enabled flag
145 		private	bool					_zoomable = true;
146 
147 		// Axis data scaleView scroll line size
148 		private	double					_smallScrollSize = double.NaN;
149 
150 		// Axis data scaleView scroll line size units type
151 		private	DateTimeIntervalType	_smallScrollSizeType = DateTimeIntervalType.Auto;
152 
153 		// Axis data scaleView scroll line minimum size
154 		private	double					_smallScrollMinSize = 1.0;
155 
156 		// Axis data scaleView scroll line minimum size units type
157 		private	DateTimeIntervalType	_smallScrollMinSizeType = DateTimeIntervalType.Auto;
158 
159         // Axis data scaleView scroll line minimum size
160         private double _currentSmallScrollSize = double.NaN;
161 
162         // Axis data scaleView scroll line minimum size units type
163         private DateTimeIntervalType    _currentSmallScrollSizeType = DateTimeIntervalType.Auto;
164 
165 		// Storage for the saved data scaleView states (position/size/sizetype)
166 		internal ArrayList				dataViewStates = null;
167 
168 #endif
169 
170 		// Ignore validation flag
171 		private	bool					_ignoreValidation = false;
172 
173 		#endregion
174 
175 		#region Constructor
176 
177 		/// <summary>
178 		/// Default constructor
179 		/// </summary>
AxisScaleView()180 		public AxisScaleView()
181 		{
182 			this.axis = null;
183 		}
184 
185 		/// <summary>
186 		/// Internal constructor.
187 		/// </summary>
188 		/// <param name="axis">Data scaleView axis.</param>
AxisScaleView(Axis axis)189         internal AxisScaleView(Axis axis)
190 		{
191 			this.axis = axis;
192 		}
193 
194 		#endregion
195 
196 		#region Axis data scaleView properties
197 
198 		/// <summary>
199 		/// Gets or sets the position of the AxisScaleView.
200 		/// </summary>
201 		[
202 		SRCategory("CategoryAttributeAxisView"),
203 		Bindable(true),
204 		DefaultValue(Double.NaN),
205 		SRDescription("DescriptionAttributeAxisDataView_Position"),
206 		TypeConverter(typeof(DoubleDateNanValueConverter)),
207 		ParenthesizePropertyNameAttribute(true)
208 		]
209 		public double Position
210 		{
211 			get
212 			{
213 				// Axis scaleView is not supported in circular chrt areas
214 				if(this.axis != null && this.axis.ChartArea != null && this.axis.ChartArea.chartAreaIsCurcular)
215 				{
216 					return Double.NaN;
217 				}
218 				return _position;
219 			}
220 			set
221 			{
222 				// Axis scaleView is not supported in circular chrt areas
223 				if(this.axis != null && this.axis.ChartArea != null && this.axis.ChartArea.chartAreaIsCurcular)
224 				{
225 					return;
226 				}
227 
228 				if(_position != value)
229 				{
230 					// Set new position
231 					_position = value;
232 
233 					// Align scaleView in connected areas
234 					if(this.axis != null && this.axis.ChartArea != null && this.axis.Common != null && this.axis.Common.ChartPicture != null)
235 					{
236 						if(!this.axis.ChartArea.alignmentInProcess)
237 						{
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);
241 						}
242 					}
243 
244 					// Validate chart
245 					if(!_ignoreValidation && axis != null)
246 					{
247 						axis.Invalidate();
248 					}
249 				}
250 			}
251 		}
252 
253 		/// <summary>
254         /// Gets or sets the size of the AxisScaleView
255 		/// </summary>
256 		[
257 		SRCategory("CategoryAttributeAxisView"),
258 		Bindable(true),
259 		DefaultValue(Double.NaN),
260 		SRDescription("DescriptionAttributeAxisDataView_Size"),
261 		TypeConverter(typeof(DoubleNanValueConverter)),
262 		ParenthesizePropertyNameAttribute(true)
263 		]
264 		public double Size
265 		{
266 			get
267 			{
268 				// Axis scaleView is not supported in circular chrt areas
269 				if(this.axis != null && this.axis.ChartArea != null && this.axis.ChartArea.chartAreaIsCurcular)
270 				{
271 					return Double.NaN;
272 				}
273 
274 				return _size;
275 			}
276 			set
277 			{
278 				// Axis scaleView is not supported in circular chrt areas
279 				if(this.axis != null && this.axis.ChartArea != null && this.axis.ChartArea.chartAreaIsCurcular)
280 				{
281 					return;
282 				}
283 
284 				if(_size != value)
285 				{
286 					// Set size value
287 					_size = value;
288 
289 
290 					// Align scaleView in connected areas
291 					if(this.axis != null && this.axis.ChartArea != null && this.axis.Common != null && this.axis.Common.ChartPicture != null)
292 					{
293 						if(!this.axis.ChartArea.alignmentInProcess)
294 						{
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);
298 						}
299 					}
300 #if Microsoft_CONTROL
301 					// Reset current scrolling line size
302 					this._currentSmallScrollSize = double.NaN;
303 #endif //Microsoft_CONTROL
304 					// Validate chart
305 					if(!_ignoreValidation && axis != null)
306 					{
307 						axis.Invalidate();
308 					}
309 				}
310 			}
311 		}
312 
313 		/// <summary>
314         /// Gets or sets the unit of measurement of the Size property.
315 		/// </summary>
316 		[
317 		SRCategory("CategoryAttributeAxisView"),
318 		Bindable(true),
319 		DefaultValue(DateTimeIntervalType.Auto),
320 		SRDescription("DescriptionAttributeAxisDataView_SizeType"),
321 		ParenthesizePropertyNameAttribute(true)
322 		]
323 		public DateTimeIntervalType SizeType
324 		{
325 			get
326 			{
327 				return _sizeType;
328 			}
329 			set
330 			{
331 				if(_sizeType != value)
332 				{
333 					// Set size type
334 					_sizeType = (value != DateTimeIntervalType.NotSet) ? value : DateTimeIntervalType.Auto;
335 
336 					// Align scaleView in connected areas
337 					if(this.axis != null && this.axis.ChartArea != null && this.axis.Common != null && this.axis.Common.ChartPicture != null)
338 					{
339 						if(!this.axis.ChartArea.alignmentInProcess)
340 						{
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);
344 						}
345 					}
346 
347 					// Validate chart
348 					if(!_ignoreValidation && axis != null)
349 					{
350 						axis.Invalidate();
351 					}
352 				}
353 			}
354 		}
355 
356         /// <summary>
357         /// Indicates if axis is zoomed-in.
358         /// </summary>
359         [
360         SRCategory("CategoryAttributeAxisView"),
361         Bindable(false),
362         Browsable(false),
363         SRDescription("DescriptionAttributeAxisDataView_IsZoomed"),
364         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
365         SerializationVisibility(SerializationVisibility.Hidden),
366         ]
367         public bool IsZoomed
368         {
369             get
370             {
371                 return (
372                     !double.IsNaN(this.Size) &&
373                     this.Size != 0.0 &&
374                     !double.IsNaN(this.Position));
375             }
376         }
377 
378 #if Microsoft_CONTROL
379 
380 		/// <summary>
381 		/// Gets or sets the minimum size of the AxisScaleView.
382 		/// </summary>
383 		[
384 		SRCategory("CategoryAttributeAxisView"),
385 		Bindable(true),
386 		DefaultValue(Double.NaN),
387 		SRDescription("DescriptionAttributeAxisDataView_MinSize"),
388 		TypeConverter(typeof(DoubleNanValueConverter))
389 		]
390 		public double MinSize
391 		{
392 			get
393 			{
394 				return _minSize;
395 			}
396 			set
397 			{
398 				_minSize = value;
399 			}
400 		}
401 
402 		/// <summary>
403 		/// Gets or sets the unit of measurement of the MinSize property.
404 		/// </summary>
405 		[
406 		SRCategory("CategoryAttributeAxisView"),
407 		Bindable(true),
408 		DefaultValue(DateTimeIntervalType.Auto),
409 		SRDescription("DescriptionAttributeAxisDataView_MinSizeType"),
410 		]
411 		public DateTimeIntervalType MinSizeType
412 		{
413 			get
414 			{
415 				return _minSizeType;
416 			}
417 			set
418 			{
419 				_minSizeType = (value != DateTimeIntervalType.NotSet) ? value : DateTimeIntervalType.Auto;
420 			}
421 		}
422 
423 		/// <summary>
424 		/// Gets or sets a flag which indicates whether the zooming user interface is enabled.
425 		/// </summary>
426 		[
427 		SRCategory("CategoryAttributeAxisView"),
428 		Bindable(true),
429 		DefaultValue(true),
430 		SRDescription("DescriptionAttributeAxisDataView_Zoomable"),
431         SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
432             Justification="'Zoomable' is a commonly used term and generally well understood"),
433 		]
434 		public bool Zoomable
435 		{
436 			get
437 			{
438 				return _zoomable;
439 			}
440 			set
441 			{
442 				_zoomable = value;
443 			}
444 		}
445 
446 		/// <summary>
447 		/// Gets or sets the small scrolling size.
448 		/// </summary>
449 		[
450 		SRCategory("CategoryAttributeAxisView"),
451 		Bindable(true),
452 		DefaultValue(Double.NaN),
453 		SRDescription("DescriptionAttributeAxisDataView_SmallScrollSize"),
454 		TypeConverter(typeof(AxisMinMaxAutoValueConverter))
455 		]
456 		public double SmallScrollSize
457 		{
458 			get
459 			{
460 				return _smallScrollSize;
461 			}
462 			set
463 			{
464 				if(_smallScrollSize != value)
465 				{
466 					// Set size value
467 					_smallScrollSize = value;
468 
469 					// Validate chart
470 					if(!_ignoreValidation && axis != null)
471 					{
472 						axis.Invalidate();
473 					}
474 				}
475 			}
476 		}
477 
478 		/// <summary>
479 		/// Gets or sets the unit of measurement for the SmallScrollMinSize property
480 		/// </summary>
481 		[
482 		SRCategory("CategoryAttributeAxisView"),
483 		Bindable(true),
484 		DefaultValue(DateTimeIntervalType.Auto),
485 		SRDescription("DescriptionAttributeAxisDataView_SmallScrollSizeType"),
486 		]
487 		public DateTimeIntervalType SmallScrollSizeType
488 		{
489 			get
490 			{
491 				return _smallScrollSizeType;
492 			}
493 			set
494 			{
495 				if(_smallScrollSizeType != value)
496 				{
497 					// Set size type
498 					_smallScrollSizeType = (value != DateTimeIntervalType.NotSet) ? value : DateTimeIntervalType.Auto;
499 
500 					// Validate chart
501 					if(!_ignoreValidation && axis != null)
502 					{
503 						axis.Invalidate();
504 					}
505 				}
506 			}
507 		}
508 
509 		/// <summary>
510 		/// Gets or sets the minimum small scrolling size.
511         /// Only used if the small scrolling size is not set.
512 		/// </summary>
513 		[
514 		SRCategory("CategoryAttributeAxisView"),
515 		Bindable(true),
516 		DefaultValue(1.0),
517 		SRDescription("DescriptionAttributeAxisDataView_SmallScrollMinSize")
518 		]
519 		public double SmallScrollMinSize
520 		{
521 			get
522 			{
523 				return _smallScrollMinSize;
524 			}
525 			set
526 			{
527 				if(_smallScrollMinSize != value)
528 				{
529                     // Set size value
530                     _smallScrollMinSize = value;
531 
532 					_currentSmallScrollSize = double.NaN;
533 
534                     // Validate chart
535 					if(!_ignoreValidation && axis != null)
536 					{
537 						axis.Invalidate();
538 					}
539 				}
540 			}
541 		}
542 
543 		/// <summary>
544 		/// Gets or sets the unit of measurement for the SmallScrollMinSize property.
545 		/// </summary>
546 		[
547 		SRCategory("CategoryAttributeAxisView"),
548 		Bindable(true),
549 		DefaultValue(DateTimeIntervalType.Auto),
550         SRDescription("DescriptionAttributeAxisDataView_SmallScrollMinSizeType"),
551 		]
552 		public DateTimeIntervalType SmallScrollMinSizeType
553 		{
554 			get
555 			{
556 				return _smallScrollMinSizeType;
557 			}
558 			set
559 			{
560 				if(_smallScrollMinSizeType != value)
561 				{
562 					// Set size type
563 					_smallScrollMinSizeType = (value != DateTimeIntervalType.NotSet) ? value : DateTimeIntervalType.Auto;
564 
565 					_currentSmallScrollSize = double.NaN;
566 
567                     // Validate chart
568 					if(!_ignoreValidation && axis != null)
569 					{
570 						axis.Invalidate();
571 					}
572 				}
573 			}
574 		}
575 
576 #endif // Microsoft_CONTROL
577 
578         #endregion
579 
580         #region ScaleView position internal methods
581 
582         /// <summary>
583         /// Call this method to get the minimum axis value of a data view.
584 		/// </summary>
585 		/// <returns>The minimum axis value for the data view.</returns>
586         [Browsable(false)]
587         [Utilities.SerializationVisibility(Utilities.SerializationVisibility.Hidden)]
588         public double ViewMinimum
589 		{
590             get
591             {
592                 // If zooming is enabled
593                 if (!Double.IsNaN(this.Size))
594                 {
595                     // If size set only use axis minimum for scaleView position
596                     if (Double.IsNaN(this.Position))
597                     {
598                         this.Position = this.axis.Minimum;
599                     }
600                     // Check if scaleView position and size are set
601                     else
602                     {
603                         // Calculate and add axis side margin
604                         if (this.Position <= axis.minimum)
605                         {
606                             return this.Position;
607                         }
608                         else // Add a margin only if scaleView is inside data point scaleView
609                         {
610                             return this.Position - axis.marginView;
611                         }
612                     }
613                 }
614 
615                 // Return axis scale minimum value if scaleView position is not set
616                 return axis.minimum;
617             }
618 		}
619 
620         /// <summary>
621         /// Maximum axis value of a data view.
622         /// </summary>
623         /// <returns>The maximum axis value for the data view.</returns>
624 		[Browsable(false)]
625         [Utilities.SerializationVisibility(Utilities.SerializationVisibility.Hidden)]
626         public double ViewMaximum
627 		{
628             get
629             {
630                 // If zooming is enabled
631                 if (!Double.IsNaN(this.Size))
632                 {
633                     // If size set only use axis minimum for scaleView position
634                     if (Double.IsNaN(this.Position))
635                     {
636                         this.Position = this.axis.Minimum;
637                     }
638 
639                     // Check if scaleView position and size are set
640                     else
641                     {
642                         // Get axis interval
643                         double viewSize = ChartHelper.GetIntervalSize(this.Position, this.Size, this.SizeType);
644 
645                         // Calculate and add axis side margin
646                         if (this.Position + viewSize >= axis.maximum)
647                         {
648                             return this.Position + viewSize;
649                         }
650                         else // Add a margin only if scaleView is inside data point scaleView
651                         {
652                             return this.Position + viewSize + axis.marginView;
653                         }
654                     }
655                 }
656 
657                 // Return axis scale maximum value if scaleView position is not set
658                 return axis.maximum;
659             }
660 		}
661 
662 		#endregion
663 
664 		#region Scrolling methods
665 
666 #if Microsoft_CONTROL
667 
668 		/// <summary>
669 		/// Call this method to scroll to a specified position along an axis.
670 		/// </summary>
671 		/// <param name="scrollType">Direction and size to scroll.</param>
Scroll(ScrollType scrollType)672 		public void Scroll(ScrollType scrollType)
673 		{
674 			this.Scroll(scrollType, false);
675 		}
676 
677 		/// <summary>
678 		/// Scrolls axis data scaleView from current position.
679 		/// </summary>
680 		/// <param name="scrollType">Direction and size to scroll.</param>
681 		/// <param name="fireChangeEvents">Fire scaleView position events from this method.</param>
Scroll(ScrollType scrollType, bool fireChangeEvents)682 		internal void Scroll(ScrollType scrollType, bool fireChangeEvents)
683 		{
684 			// Adjust current position depending on the scroll type
685 			double	newPosition = this._position;
686 			switch(scrollType)
687 			{
688 				case(ScrollType.SmallIncrement):
689                     newPosition += ((axis.IsReversed) ? -1 : 1) * ChartHelper.GetIntervalSize(this._position, this.GetScrollingLineSize(), this.GetScrollingLineSizeType());
690 					break;
691 				case(ScrollType.SmallDecrement):
692                     newPosition -= ((axis.IsReversed) ? -1 : 1) * ChartHelper.GetIntervalSize(this._position, this.GetScrollingLineSize(), this.GetScrollingLineSizeType());
693 					break;
694 				case(ScrollType.LargeIncrement):
695                     newPosition += ((axis.IsReversed) ? -1 : 1) * ChartHelper.GetIntervalSize(this._position, this.Size, this.SizeType);
696 					break;
697 				case(ScrollType.LargeDecrement):
698                     newPosition -= ((axis.IsReversed) ? -1 : 1) * ChartHelper.GetIntervalSize(this._position, this.Size, this.SizeType);
699 					break;
700 				case(ScrollType.First):
701 					if(!axis.IsReversed)
702 					{
703 						newPosition = (axis.minimum + axis.marginView);
704 					}
705 					else
706 					{
707 						newPosition = (axis.maximum - axis.marginView);
708 					}
709 					break;
710 				case(ScrollType.Last):
711 				{
712                     double viewSize = ChartHelper.GetIntervalSize(newPosition, this.Size, this.SizeType);
713 					if(!axis.IsReversed)
714 					{
715 						newPosition = (axis.maximum - axis.marginView - viewSize);
716 					}
717 					else
718 					{
719 						newPosition = (axis.minimum + axis.marginView + viewSize);
720 					}
721 					break;
722 				}
723 			}
724 
725 			// Scroll to the new position
726 			this.Scroll(newPosition, fireChangeEvents);
727 		}
728 
729         /// <summary>
730 		/// Call this method to scroll to a specified position along an axis.
731 		/// </summary>
732 		/// <param name="newPosition">New position.</param>
Scroll(double newPosition)733 		public void Scroll(double newPosition)
734 		{
735 			this.Scroll(newPosition, false);
736 		}
737 
738         /// <summary>
739         /// Call this method to scroll to a specified position along an axis.
740         /// </summary>
741         /// <param name="newPosition">New position.</param>
Scroll(DateTime newPosition)742         public void Scroll(DateTime newPosition)
743         {
744             this.Scroll(newPosition.ToOADate(), false);
745         }
746 
747 		/// <summary>
748 		/// Internal helper method for scrolling into specified position.
749 		/// </summary>
750 		/// <param name="newPosition">New data scaleView position.</param>
751 		/// <param name="fireChangeEvents">Fire scaleView position events from this method.</param>
Scroll(double newPosition, bool fireChangeEvents)752 		internal void Scroll(double newPosition, bool fireChangeEvents)
753 		{
754 			// Get current scaleView size
755             double viewSize = ChartHelper.GetIntervalSize(newPosition, this.Size, this.SizeType);
756 
757             // Validate new scaleView position
758 			if(newPosition < (axis.minimum + axis.marginView))
759 			{
760 				newPosition = (axis.minimum + axis.marginView);
761 			}
762 			else if(newPosition > (axis.maximum - axis.marginView - viewSize))
763 			{
764 				newPosition = (axis.maximum - axis.marginView - viewSize);
765 			}
766 
767             // Fire scaleView position changing events
768 			ViewEventArgs	arguments = new ViewEventArgs(this.axis, newPosition, this.Size, this.SizeType);
769 			if(fireChangeEvents && GetChartObject() != null)
770 			{
771 				GetChartObject().OnAxisViewChanging(arguments);
772 				newPosition = arguments.NewPosition;
773 			}
774 
775 			// Check if data scaleView position and size is different from current
776 			if(newPosition == this.Position)
777 			{
778 				return;
779 			}
780 
781 			// Change scaleView position
782 			this.Position = newPosition;
783 
784 			// Fire scaleView position changed events
785 			if(fireChangeEvents && GetChartObject() != null)
786 			{
787 				GetChartObject().OnAxisViewChanged(arguments);
788 			}
789 		}
790 
791 #endif
792         #endregion
793 
794         #region Zooming and ZoomResetting methods
795 
796 #if Microsoft_CONTROL
797 
798 		/// <summary>
799 		/// Sets a new axis data view/position based on the start and end dates specified.
800 		/// </summary>
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>
Zoom(double viewPosition, double viewSize, DateTimeIntervalType viewSizeType, bool saveState)805 		public void Zoom(double viewPosition, double viewSize, DateTimeIntervalType viewSizeType, bool saveState)
806 		{
807 			this.Zoom(viewPosition, viewSize, viewSizeType, false, saveState);
808 		}
809 
810 		/// <summary>
811 		/// Sets a new axis data view/position based on the specified start and end values.
812 		/// </summary>
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>
Zoom(double viewStart, double viewEnd)815 		public void Zoom(double viewStart, double viewEnd)
816 		{
817 			this.Zoom(viewStart, viewEnd - viewStart, DateTimeIntervalType.Number, false, false);
818 		}
819 
820 		/// <summary>
821 		/// Sets a new axis data view/position based on the start and end dates specified.
822 		/// </summary>
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>
Zoom(double viewPosition, double viewSize, DateTimeIntervalType viewSizeType)826 		public void Zoom(double viewPosition, double viewSize, DateTimeIntervalType viewSizeType)
827 		{
828 			this.Zoom(viewPosition, viewSize, viewSizeType, false, false);
829         }
830 
831         /// <summary>
832 		/// Reset the specified number of zooming operations by restoring axis data view.
833 		/// </summary>
834 		/// <param name="numberOfViews">Number of zoom operations to reset. Zero for all.</param>
ZoomReset(int numberOfViews)835 		public void ZoomReset(int numberOfViews)
836 		{
837 			this.LoadDataViewState(numberOfViews, false);
838 		}
839 
840 		/// <summary>
841 		/// Reset one zooming operation by restoring axis data view.
842 		/// </summary>
ZoomReset()843 		public void ZoomReset()
844 		{
845 			this.LoadDataViewState(1, false);
846 		}
847 
848 		/// <summary>
849 		/// Reset several zooming operation by restoring data scaleView size/position.
850 		/// </summary>
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>
ZoomReset(int numberOfViews, bool fireChangeEvents)853 		internal void ZoomReset(int numberOfViews, bool fireChangeEvents)
854 		{
855 			this.LoadDataViewState(numberOfViews, fireChangeEvents);
856 		}
857 
858         /// <summary>
859 		/// Internal helper zooming method.
860 		/// </summary>
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>
Zoom( double viewPosition, double viewSize, DateTimeIntervalType viewSizeType, bool fireChangeEvents, bool saveState)867 		internal bool Zoom(
868 			double viewPosition,
869 			double viewSize,
870 			DateTimeIntervalType viewSizeType,
871 			bool fireChangeEvents,
872 			bool saveState)
873 		{
874 			// Validate new scaleView position and size
875 			ValidateViewPositionSize(ref viewPosition, ref viewSize, ref viewSizeType);
876 
877 			// Fire scaleView position/size changing events
878 			ViewEventArgs	arguments = new ViewEventArgs(this.axis, viewPosition, viewSize, viewSizeType);
879 			if(fireChangeEvents && GetChartObject() != null)
880 			{
881 				GetChartObject().OnAxisViewChanging(arguments);
882 				viewPosition = arguments.NewPosition;
883 				viewSize = arguments.NewSize;
884 				viewSizeType = arguments.NewSizeType;
885 			}
886 
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)
891 			{
892 				return false;
893 			}
894 
895 			// Save current data scaleView state, so it can be restored
896 			if(saveState)
897 			{
898 				SaveDataViewState();
899 			}
900 
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;
907 
908 			// Reset current scrolling line size
909 			this._currentSmallScrollSize = double.NaN;
910 
911 			// Invalidate chart
912             axis.Invalidate();
913 
914 			// Fire scaleView position/size changed events
915 			if(fireChangeEvents && GetChartObject() != null)
916 			{
917 				GetChartObject().OnAxisViewChanged(arguments);
918 			}
919 
920 			return true;
921 		}
922 
923 #endif
924 
925         #endregion
926 
927         #region Data scaleView state saving/restoring methods
928 
929 #if Microsoft_CONTROL
930 
931 		/// <summary>
932 		/// Saves current data scaleView position/size/sizetype, so
933 		/// it can be restored later.
934 		/// </summary>
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>
LoadDataViewState(int numberOfViews, bool fireChangeEvents)937 		private void LoadDataViewState(int numberOfViews, bool fireChangeEvents)
938 		{
939 			// Check parameters
940 			if(numberOfViews < 0)
941 			{
942                 throw (new ArgumentOutOfRangeException("numberOfViews", SR.ExceptionScrollBarZoomResetsNumberInvalid));
943 			}
944 			// Check if storage was created
945 			if(dataViewStates != null && dataViewStates.Count >= 3)
946 			{
947 				// Find starting index of restoring state
948 				int	dataStartIndex = 0;
949 				if(numberOfViews > 0)
950 				{
951 					dataStartIndex = dataViewStates.Count - numberOfViews * 3;
952 					if(dataStartIndex < 0)
953 					{
954 						dataStartIndex = 0;
955 					}
956 				}
957 
958 
959 				// Fire scaleView position/size changing events
960 				ViewEventArgs	arguments = new ViewEventArgs(
961 					this.axis,
962 					(double)dataViewStates[dataStartIndex],
963 					(double)dataViewStates[dataStartIndex + 1],
964 					(DateTimeIntervalType)dataViewStates[dataStartIndex + 2]);
965 				if(fireChangeEvents && GetChartObject() != null)
966 				{
967 					GetChartObject().OnAxisViewChanging(arguments);
968 				}
969 
970                 // Restore data
971 				this.Position	= arguments.NewPosition;
972 				this.Size		= arguments.NewSize;
973 				this.SizeType	= arguments.NewSizeType;
974 
975 				// Fire scaleView position/size changed events
976 				if(fireChangeEvents && GetChartObject() != null)
977 				{
978 					GetChartObject().OnAxisViewChanged(arguments);
979 				}
980 
981                 // Clear data
982                 int itemsToRemove = numberOfViews * 3;
983                 if (itemsToRemove > (dataViewStates.Count - dataStartIndex))
984                 {
985                     itemsToRemove = dataViewStates.Count - dataStartIndex;
986                 }
987                 dataViewStates.RemoveRange(dataStartIndex, itemsToRemove);
988 
989 
990                 // clean up the history state when the numberOfViews == 0 (reset all by docs)
991                 if ( numberOfViews == 0 )
992                 {
993                     dataViewStates.Clear();
994                 }
995                 if (Double.IsNaN(this.Position) || Double.IsNaN(this.Size))
996                 {
997                     this.Position = Double.NaN;
998                     this.Size = Double.NaN;
999                 }
1000 
1001             }
1002 
1003 			// Nothing to restore - just disable the data scaleView
1004 			else
1005 			{
1006 				// Fire scaleView position/size changing events
1007 				ViewEventArgs	arguments = new ViewEventArgs(
1008 					this.axis,
1009 					double.NaN,
1010 					double.NaN,
1011 					DateTimeIntervalType.Auto);
1012 
1013 				if(fireChangeEvents && GetChartObject() != null)
1014 				{
1015 					GetChartObject().OnAxisViewChanging(arguments);
1016 				}
1017 
1018                 // Restore data
1019 				this.Position	= arguments.NewPosition;
1020 				this.Size		= arguments.NewSize;
1021 				this.SizeType	= arguments.NewSizeType;
1022 
1023 				// Fire scaleView position/size changed events
1024 				if(fireChangeEvents && GetChartObject() != null)
1025 				{
1026 					GetChartObject().OnAxisViewChanged(arguments);
1027 				}
1028     		}
1029             // clear cached chart areas and bitmap buffers
1030             GetChartObject().Refresh();
1031 		}
1032 
1033 		/// <summary>
1034 		/// Saves current data scaleView position/size/sizetype, so
1035 		/// it can be restored later.
1036 		/// </summary>
SaveDataViewState()1037 		private void SaveDataViewState()
1038 		{
1039 			// Create storage array
1040 			if(dataViewStates == null)
1041 			{
1042 				dataViewStates = new ArrayList();
1043 			}
1044 
1045 			// Save data scaleView state
1046 			dataViewStates.Add(this.Position);
1047 			dataViewStates.Add(this.Size);
1048 			dataViewStates.Add(this.SizeType);
1049 		}
1050 #endif
1051 
1052         #endregion
1053 
1054         #region Helper methods
1055 
1056 #if Microsoft_CONTROL
1057 		/// <summary>
1058 		/// Initialize internal scrolling line size variables for later use.
1059 		/// This size is used in to scroll chart one line up or down.
1060 		/// </summary>
GetCurrentViewSmallScrollSize()1061 		private void GetCurrentViewSmallScrollSize()
1062 		{
1063 			//**************************************************************************
1064 			//** Check if current scrolling line size was not already calculated
1065 			//**************************************************************************
1066 			if(double.IsNaN(_currentSmallScrollSize))
1067 			{
1068 				//**************************************************************************
1069 				//** Calculate line size depending on the current scaleView size
1070 				//**************************************************************************
1071 				if(this.SizeType == DateTimeIntervalType.Auto || this.SizeType == DateTimeIntervalType.Number)
1072 				{
1073 					// Set line size type
1074 					_currentSmallScrollSizeType = DateTimeIntervalType.Number;
1075 
1076 					// Devide scaleView by 20 to find the scrolling line size
1077 					double newSize = this.Size / 20.0;
1078 
1079 					// Make sure that current line size is even with minimum value
1080 					if(!double.IsNaN(this.SmallScrollMinSize) && this.SmallScrollMinSize != 0.0)
1081 					{
1082 						double rounder = (Math.Round(newSize / this.SmallScrollMinSize));
1083 						if(rounder < 0)
1084 						{
1085 							rounder = 1;
1086 						}
1087 						newSize = rounder * this.SmallScrollMinSize;
1088 					}
1089 
1090 					// Set new current line size
1091 					this._currentSmallScrollSize = newSize;
1092 				}
1093 				else
1094 				{
1095 					// Calculate line size for date/time
1096                     double viewEndPosition = this.Position + ChartHelper.GetIntervalSize(this.Position, this.Size, this.SizeType);
1097 					_currentSmallScrollSize = axis.CalcInterval(
1098 						this.Position,
1099 						viewEndPosition,
1100 						true,
1101 						out _currentSmallScrollSizeType,
1102 						ChartValueType.Auto);
1103 				}
1104 
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)
1109 				{
1110                     double newLineSize = ChartHelper.GetIntervalSize(this.Position, _currentSmallScrollSize, _currentSmallScrollSizeType);
1111                     double minLineSize = ChartHelper.GetIntervalSize(this.Position, this.SmallScrollMinSize, this.SmallScrollMinSizeType);
1112 					if(newLineSize < minLineSize)
1113 					{
1114 						_currentSmallScrollSize = SmallScrollMinSize;
1115 						_currentSmallScrollSizeType = SmallScrollMinSizeType;
1116 					}
1117 				}
1118 			}
1119 		}
1120 
1121 		/// <summary>
1122 		/// Returns the scroll line size.
1123 		/// </summary>
1124 		/// <returns>Scroll line size.</returns>
GetScrollingLineSize()1125 		internal double GetScrollingLineSize()
1126 		{
1127 			// Scroll line size/type is specificly set by user
1128 			if(!double.IsNaN(this.SmallScrollSize))
1129 			{
1130 				return this.SmallScrollSize;
1131 			}
1132 
1133 			// Calcualte scroll line size depending on the current scaleView size
1134 			GetCurrentViewSmallScrollSize();
1135 
1136 			// Return line size
1137 			return _currentSmallScrollSize;
1138 		}
1139 
1140 		/// <summary>
1141 		/// Returns the scroll line size units type.
1142 		/// </summary>
1143 		/// <returns>Scroll line size units type.</returns>
GetScrollingLineSizeType()1144 		internal DateTimeIntervalType GetScrollingLineSizeType()
1145 		{
1146 			// Scroll line size/type is specificly set by user
1147 			if(!double.IsNaN(this.SmallScrollSize))
1148 			{
1149 				return this.SmallScrollSizeType;
1150 			}
1151 
1152 			// Calcualte scroll line size depending on the current scaleView size
1153 			GetCurrentViewSmallScrollSize();
1154 
1155 			// Return line size units type
1156 			return _currentSmallScrollSizeType;
1157 		}
1158 
1159 		/// <summary>
1160 		/// Helper method, which validates the axis data scaleView position and size.
1161 		/// Returns adjusted scaleView position and size.
1162 		/// </summary>
1163 		/// <param name="viewPosition">ScaleView position.</param>
1164 		/// <param name="viewSize">ScaleView size.</param>
1165 		/// <param name="viewSizeType">ScaleView size units type.</param>
ValidateViewPositionSize(ref double viewPosition, ref double viewSize, ref DateTimeIntervalType viewSizeType)1166 		private void ValidateViewPositionSize(ref double viewPosition, ref double viewSize, ref DateTimeIntervalType viewSizeType)
1167 		{
1168 			//****************************************************************
1169 			//** Check if new scaleView position is inside axis scale
1170 			//** minimum/maximum without margin.
1171 			//****************************************************************
1172 			if(viewPosition < (axis.minimum + axis.marginView))
1173 			{
1174 				if(viewSizeType == DateTimeIntervalType.Auto || viewSizeType == DateTimeIntervalType.Number)
1175 				{
1176 					viewSize -= (axis.minimum + axis.marginView) - viewPosition;
1177 				}
1178 				viewPosition = (axis.minimum + axis.marginView);
1179 			}
1180 			else if(viewPosition > (axis.maximum - axis.marginView))
1181 			{
1182                 if(viewSizeType == DateTimeIntervalType.Auto || viewSizeType == DateTimeIntervalType.Number)
1183 				{
1184 					viewSize -= viewPosition - (axis.maximum - axis.marginView);
1185 				}
1186 				viewPosition = (axis.maximum - axis.marginView);
1187 			}
1188 
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))
1196 			{
1197                 minViewSize = ChartHelper.GetIntervalSize(viewPosition, this.MinSize, this.MinSizeType);
1198 				if(newViewSize < minViewSize)
1199 				{
1200 					viewSize = (double.IsNaN(this.MinSize)) ? 1 : this.MinSize;
1201 					viewSizeType = this.MinSizeType;
1202                     newViewSize = ChartHelper.GetIntervalSize(viewPosition, viewSize, viewSizeType);
1203 				}
1204 			}
1205 
1206 			//****************************************************************
1207 			//** Check if new scaleView size is smaller than (0.000000001)
1208 			//****************************************************************
1209 			if(newViewSize < 0.000000001)
1210 			{
1211 				viewSize = 0.000000001;
1212 				viewSizeType = DateTimeIntervalType.Number;
1213                 newViewSize = ChartHelper.GetIntervalSize(viewPosition, viewSize, viewSizeType);
1214 			}
1215 
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) )
1221 			{
1222 				double	currentSize = viewSize;
1223 				DateTimeIntervalType currentSizeType = viewSizeType;
1224 
1225 				// Try to reduce the scaleView size
1226 				if(newViewSize > minViewSize)
1227 				{
1228 					// Try to adjust the scaleView size
1229 					if(viewSize > 1)
1230 					{
1231 						--viewSize;
1232 					}
1233 					else if(viewSizeType == DateTimeIntervalType.Years)
1234 					{
1235 						viewSize = 11;
1236 						viewSizeType = DateTimeIntervalType.Months;
1237 					}
1238 					else if(viewSizeType == DateTimeIntervalType.Months)
1239 					{
1240 						viewSize = 4;
1241 						viewSizeType = DateTimeIntervalType.Weeks;
1242 					}
1243 					else if(viewSizeType == DateTimeIntervalType.Weeks)
1244 					{
1245 						viewSize = 6;
1246 						viewSizeType = DateTimeIntervalType.Days;
1247 					}
1248 					else if(viewSizeType == DateTimeIntervalType.Days)
1249 					{
1250 						viewSize = 23;
1251 						viewSizeType = DateTimeIntervalType.Hours;
1252 					}
1253 					else if(viewSizeType == DateTimeIntervalType.Hours)
1254 					{
1255 						viewSize = 59;
1256 						viewSizeType = DateTimeIntervalType.Minutes;
1257 					}
1258 					else if(viewSizeType == DateTimeIntervalType.Minutes)
1259 					{
1260 						viewSize = 59;
1261 						viewSizeType = DateTimeIntervalType.Seconds;
1262 					}
1263 					else if(viewSizeType == DateTimeIntervalType.Seconds)
1264 					{
1265 						viewSize = 999;
1266 						viewSizeType = DateTimeIntervalType.Milliseconds;
1267 					}
1268 					else
1269 					{
1270 						viewPosition = (axis.maximum - axis.marginView) - minViewSize;
1271 						break;
1272 					}
1273 
1274 					// Double check that scaleView size is not smaller than min size
1275                     newViewSize = ChartHelper.GetIntervalSize(viewPosition, viewSize, viewSizeType);
1276 					if(newViewSize < minViewSize)
1277 					{
1278 						// Can't adjust size no more (restore prev. value)
1279 						viewSize = currentSize;
1280 						viewSizeType = currentSizeType;
1281 
1282 						// Adjust the start position
1283 						viewPosition = (axis.maximum - axis.marginView) - minViewSize;
1284 						break;
1285 					}
1286 				}
1287 				else
1288 				{
1289 					// Adjust the start position
1290 					viewPosition = (axis.maximum - axis.marginView) - newViewSize;
1291 					break;
1292 				}
1293 			}
1294         }
1295 
1296         /// <summary>
1297 		/// Helper function which returns a reference to the chart object.
1298 		/// </summary>
1299 		/// <returns>Chart object reference.</returns>
GetChartObject()1300 		internal Chart GetChartObject()
1301 		{
1302 			if(this.axis != null && this.axis.Common!=null)
1303 			{
1304     			return this.axis.Common.Chart;
1305 			}
1306 
1307 			return null;
1308         }
1309 #endif //Microsoft_CONTROL
1310 
1311         #endregion
1312     }
1313 
1314 #if Microsoft_CONTROL
1315 
1316 	/// <summary>
1317 	/// This class is used as a parameter object in the AxisViewChanged and AxisViewChanging events of the root Chart object.
1318 	/// </summary>
1319 	public class ViewEventArgs : EventArgs
1320 	{
1321     #region Private fields
1322 
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;
1328 
1329         #endregion
1330 
1331     #region Constructors
1332 
1333 			/// <summary>
1334 			/// ViewEventArgs constructor.
1335 			/// </summary>
1336 			/// <param name="axis">Axis of the scale view.</param>
1337 			/// <param name="newPosition">New scale view start position.</param>
ViewEventArgs(Axis axis, double newPosition)1338 			public ViewEventArgs(Axis axis, double newPosition)
1339 			{
1340 				this._axis = axis;
1341 				this._newPosition = newPosition;
1342 			}
1343 
1344 			/// <summary>
1345 			/// ViewEventArgs constructor.
1346 			/// </summary>
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>
ViewEventArgs(Axis axis, double newPosition, double newSize, DateTimeIntervalType newSizeType)1351 			public ViewEventArgs(Axis axis, double newPosition, double newSize, DateTimeIntervalType newSizeType)
1352 			{
1353 				this._axis = axis;
1354 				this._newPosition = newPosition;
1355 				this._newSize = newSize;
1356 				this._newSizeType = newSizeType;
1357 			}
1358 
1359     #endregion
1360 
1361     #region Properties
1362 
1363 		/// <summary>
1364 		/// Axis of the event.
1365 		/// </summary>
1366 		[
1367 		SRDescription("DescriptionAttributeAxis"),
1368 		]
1369 		public Axis Axis
1370 		{
1371 			get
1372 			{
1373 				return _axis;
1374 			}
1375 		}
1376 
1377 		/// <summary>
1378 		/// ChartArea of the event.
1379 		/// </summary>
1380 		[
1381 		SRDescription("DescriptionAttributeChartArea"),
1382 		]
1383 		public ChartArea ChartArea
1384 		{
1385 			get
1386 			{
1387 				return _axis.ChartArea;
1388 			}
1389 		}
1390 
1391 		/// <summary>
1392 		/// New scale view start position.
1393 		/// </summary>
1394 		[
1395 		SRDescription("DescriptionAttributeViewEventArgs_NewPosition"),
1396 		]
1397 		public double NewPosition
1398 		{
1399 			get
1400 			{
1401 				return _newPosition;
1402 			}
1403 			set
1404 			{
1405 				_newPosition = value;
1406 			}
1407 		}
1408 
1409 		/// <summary>
1410 		/// New scale view size.
1411 		/// </summary>
1412 		[
1413 		SRDescription("DescriptionAttributeViewEventArgs_NewSize"),
1414 		]
1415 		public double NewSize
1416 		{
1417 			get
1418 			{
1419 				return _newSize;
1420 			}
1421 			set
1422 			{
1423 				_newSize = value;
1424 			}
1425 		}
1426 
1427 		/// <summary>
1428 		/// New unit of measurement of the scale view.
1429 		/// </summary>
1430 		[
1431 		SRDescription("DescriptionAttributeViewEventArgs_NewSizeType"),
1432 		]
1433 		public DateTimeIntervalType NewSizeType
1434 		{
1435 			get
1436 			{
1437 				return _newSizeType;
1438 			}
1439 			set
1440 			{
1441 				_newSizeType = (value != DateTimeIntervalType.NotSet) ? value : DateTimeIntervalType.Auto;
1442 			}
1443 		}
1444 
1445     #endregion
1446 	}
1447 
1448 #endif	// #if Microsoft_CONTROL
1449 }
1450 
1451 #if Microsoft_CONTROL
1452 	namespace System.Windows.Forms.DataVisualization.Charting
1453 #else
1454 	namespace System.Web.UI.DataVisualization.Charting
1455 #endif
1456 {
1457 	/// <summary>
1458 	/// Designer converter class
1459 	/// Converts Double.NaN values to/from "Not set".
1460 	/// </summary>
1461 	internal class DoubleNanValueConverter : DoubleConverter
1462 	{
1463 		#region Converter methods
1464 
1465 		/// <summary>
1466 		/// Standard values supported.  This method always return true.
1467 		/// </summary>
1468 		/// <param name="context">Descriptor context.</param>
1469 		/// <returns>True.</returns>
GetStandardValuesSupported(ITypeDescriptorContext context)1470 		public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
1471 		{
1472 			return true;
1473 		}
1474 
1475 		/// <summary>
1476 		/// Standard values are not exclusive.  This method always return false.
1477 		/// </summary>
1478 		/// <param name="context">Descriptor context.</param>
1479 		/// <returns>False.</returns>
GetStandardValuesExclusive(ITypeDescriptorContext context)1480 		public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
1481 		{
1482 			return false;
1483 		}
1484 
1485 		/// <summary>
1486 		/// Get in the collection of standard values.
1487 		/// </summary>
1488 		/// <param name="context">Descriptor context.</param>
GetStandardValues(ITypeDescriptorContext context)1489 		public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
1490 		{
1491 			ArrayList values = new ArrayList();
1492 			values.Add(Double.NaN);
1493 
1494 			return new StandardValuesCollection(values);
1495 		}
1496 
1497         /// <summary>
1498         /// Convert double.NaN to string "Not set"
1499         /// </summary>
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>
ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)1505 		public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
1506 		{
1507 			double	doubleValue = (double)value;
1508 			if (destinationType == typeof(string))
1509 			{
1510 				if(Double.IsNaN(doubleValue))
1511 				{
1512                     return Constants.NotSetValue;
1513 				}
1514 			}
1515 
1516 			// Call base class
1517 			return base.ConvertTo(context, culture, value, destinationType);
1518 		}
1519 
1520 		/// <summary>
1521 		/// Convert minimum or maximum values from string.
1522 		/// </summary>
ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)1523 		public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
1524 		{
1525 			// If converting from string value
1526             string crossingValue = value as string;
1527             if (crossingValue != null)
1528 			{
1529                 if (String.Compare(crossingValue, Constants.NotSetValue, StringComparison.OrdinalIgnoreCase) == 0)
1530 				{
1531 					return Double.NaN;
1532 				}
1533 			}
1534 
1535 			// Call base converter
1536 			return base.ConvertFrom(context, culture, value);
1537 		}
1538 
1539 			#endregion
1540 	}
1541 
1542 	/// <summary>
1543 	/// Designer converter class
1544 	/// Converts Double.NaN values to/from "Not set".
1545 	/// Converts value to/from date strings.
1546 	/// </summary>
1547     internal class DoubleDateNanValueConverter : DoubleConverter
1548 	{
1549 		#region Converter methods
1550 
1551 		/// <summary>
1552 		/// Standard values supported - return true
1553 		/// </summary>
1554 		/// <param name="context">Descriptor context.</param>
1555 		/// <returns>Standard values supported.</returns>
GetStandardValuesSupported(ITypeDescriptorContext context)1556 		public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
1557 		{
1558 			return true;
1559 		}
1560 
1561 		/// <summary>
1562 		/// Standard values are not exclusive - return false
1563 		/// </summary>
1564 		/// <param name="context">Descriptor context.</param>
1565 		/// <returns>Non exclusive standard values.</returns>
GetStandardValuesExclusive(ITypeDescriptorContext context)1566 		public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
1567 		{
1568 			return false;
1569 		}
1570 
1571 		/// <summary>
1572 		/// Fill in the list of predefined values.
1573 		/// </summary>
1574 		/// <param name="context">Descriptor context.</param>
GetStandardValues(ITypeDescriptorContext context)1575 		public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
1576 		{
1577 			ArrayList values = new ArrayList();
1578 			values.Add(Double.NaN);
1579 
1580 			return new StandardValuesCollection(values);
1581 		}
1582 
1583         /// <summary>
1584         /// Convert values to string if step type is set to one of the DateTime type
1585         /// </summary>
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>
ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)1591 		public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
1592 		{
1593 			// Check for NaN
1594 			if (destinationType == typeof(string))
1595 			{
1596 				if(Double.IsNaN((double)value))
1597 				{
1598                     return Constants.NotSetValue;
1599 				}
1600 			}
1601 
1602 			if (context != null && context.Instance != null)
1603 			{
1604 				// Get access to the Axis object
1605 				Axis axis = null;
1606 				if(context.Instance is AxisScaleView)
1607 				{
1608 					axis = ((AxisScaleView)context.Instance).axis;
1609 				}
1610 
1611 #if Microsoft_CONTROL
1612 
1613 				else if(context.Instance is Cursor)
1614 				{
1615 					axis = ((Cursor)context.Instance).GetAxis();
1616 				}
1617 #endif // Microsoft_CONTROL
1618 
1619 				if (axis != null && destinationType == typeof(string))
1620 				{
1621                     string strValue = ConvertDateTimeToString(
1622                         (double)value,
1623                         axis.GetAxisValuesType(),
1624                         axis.InternalIntervalType);
1625 
1626                     if (strValue != null)
1627                         return strValue;
1628 				}
1629 
1630 			}
1631 			return base.ConvertTo(context, culture, value, destinationType);
1632 		}
1633 
ConvertDateTimeToString( double dtValue, ChartValueType axisValuesType, DateTimeIntervalType dtIntervalType)1634         public static string ConvertDateTimeToString(
1635             double dtValue,
1636             ChartValueType axisValuesType,
1637             DateTimeIntervalType dtIntervalType)
1638         {
1639             string strValue = null;
1640             // Use axis values types if interval is automatic
1641             if (dtIntervalType == DateTimeIntervalType.Auto)
1642             {
1643                 if (axisValuesType == ChartValueType.DateTime ||
1644                     axisValuesType == ChartValueType.Time ||
1645                     axisValuesType == ChartValueType.Date ||
1646                     axisValuesType == ChartValueType.DateTimeOffset)
1647                 {
1648                     strValue = DateTime.FromOADate(dtValue).ToString("g", System.Globalization.CultureInfo.CurrentCulture);
1649                 }
1650             }
1651             else
1652             {
1653                 if (dtIntervalType != DateTimeIntervalType.Number)
1654                 {
1655                     // Covert value to date/time
1656                     if (dtIntervalType < DateTimeIntervalType.Hours)
1657                     {
1658                         strValue = DateTime.FromOADate(dtValue).ToShortDateString();
1659                     }
1660                     else
1661                     {
1662                         strValue = DateTime.FromOADate(dtValue).ToString("g", System.Globalization.CultureInfo.CurrentCulture);
1663                     }
1664                 }
1665             }
1666 
1667             if (axisValuesType == ChartValueType.DateTimeOffset && strValue != null)
1668                 strValue += " +0";
1669 
1670             return strValue;
1671         }
1672 
1673 		/// <summary>
1674 		/// Convert Min and Max values from string if step type is set to one of the DateTime type
1675 		/// </summary>
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>
ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)1680 		public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
1681 		{
1682 			object	result = null;
1683 			bool	convertFromDate = false;
1684 
1685 			// If converting from string value
1686             string crossingValue = value as string;
1687 			if (crossingValue != null)
1688 			{
1689                 if (String.Compare(crossingValue, Constants.NotSetValue, StringComparison.OrdinalIgnoreCase) == 0)
1690 				{
1691 					return Double.NaN;
1692 				}
1693 			}
1694 
1695 			// If context interface provided check if we are dealing with DateTime values
1696 			if (context != null && context.Instance != null && context.Instance is Axis)
1697 			{
1698 
1699 				// Get axis object
1700 				Axis	axis = null;
1701 				if(context.Instance is AxisScaleView)
1702 				{
1703 					axis = ((AxisScaleView)context.Instance).axis;
1704 				}
1705 
1706 #if Microsoft_CONTROL
1707 				else if(context.Instance is Cursor)
1708 				{
1709 					axis = ((Cursor)context.Instance).GetAxis();
1710 				}
1711 #endif // Microsoft_CONTROL
1712 
1713                 if (axis != null && crossingValue != null)
1714 				{
1715 					if(axis.InternalIntervalType == DateTimeIntervalType.Auto)
1716 					{
1717 						if(axis.GetAxisValuesType() == ChartValueType.DateTime ||
1718 							axis.GetAxisValuesType() == ChartValueType.Date ||
1719 							axis.GetAxisValuesType() == ChartValueType.Time ||
1720                             axis.GetAxisValuesType() == ChartValueType.DateTimeOffset)
1721 						{
1722 							convertFromDate = true;
1723 						}
1724 					}
1725 					else
1726 					{
1727 						if(axis.InternalIntervalType != DateTimeIntervalType.Number)
1728 						{
1729 							convertFromDate = true;
1730 						}
1731 					}
1732 				}
1733 			}
1734 
1735 			// Try to convert from double string
1736             try
1737             {
1738                 result = base.ConvertFrom(context, culture, value);
1739             }
1740             catch (ArgumentException)
1741             {
1742                 result = null;
1743             }
1744             catch (NotSupportedException)
1745             {
1746                 result = null;
1747             }
1748 
1749 			// Try to convert from date/time string
1750             if (crossingValue != null && (convertFromDate || result == null))
1751             {
1752                 DateTime valueAsDate;
1753                 bool parseSucceed = DateTime.TryParse(crossingValue, CultureInfo.InvariantCulture, DateTimeStyles.None, out valueAsDate);
1754 
1755                 if (parseSucceed)
1756                 {
1757                     return valueAsDate.ToOADate();
1758                 }
1759             }
1760 
1761 			// Call base converter
1762 			return base.ConvertFrom(context, culture, value);
1763 		}
1764 
1765 	#endregion
1766 	}
1767 
1768 }
1769 
1770 
1771