Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Web.DataVisualization / Common / General / AxisScrollZoom.cs
1 //-------------------------------------------------------------
2 // <copyright company=\92Microsoft Corporation\92>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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
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>
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