Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Diagnostics.CodeAnalysis;
- using System.Linq;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Shapes;
- using EF = System.Windows.Controls.DataVisualization.EnumerableFunctions;
- using System.Windows.Controls.DataVisualization.Charting;
- using System.Windows.Controls.DataVisualization;
- namespace SilverlightApplication3
- {
- /// <summary>
- /// An axis that displays numeric values.
- /// </summary>
- [StyleTypedProperty(Property = "GridLineStyle", StyleTargetType = typeof(Line))]
- [StyleTypedProperty(Property = "MajorTickMarkStyle", StyleTargetType = typeof(Line))]
- [StyleTypedProperty(Property = "MinorTickMarkStyle", StyleTargetType = typeof(Line))]
- [StyleTypedProperty(Property = "AxisLabelStyle", StyleTargetType = typeof(DateTimeAxisLabel))]
- [StyleTypedProperty(Property = "TitleStyle", StyleTargetType = typeof(Title))]
- [TemplatePart(Name = AxisGridName, Type = typeof(Grid))]
- [TemplatePart(Name = AxisTitleName, Type = typeof(Title))]
- public class DateTimeAxis : RangeAxis
- {
- #region public DateTime? ActualMaximum
- /// <summary>
- /// Gets the actual maximum value plotted on the chart.
- /// </summary>
- public DateTime? ActualMaximum
- {
- get { return (DateTime?)GetValue(ActualMaximumProperty); }
- private set { SetValue(ActualMaximumProperty, value); }
- }
- /// <summary>
- /// Identifies the ActualMaximum dependency property.
- /// </summary>
- public static readonly DependencyProperty ActualMaximumProperty =
- DependencyProperty.Register(
- "ActualMaximum",
- typeof(DateTime?),
- typeof(DateTimeAxis),
- null);
- #endregion public DateTime? ActualMaximum
- #region public DateTime? ActualMinimum
- /// <summary>
- /// Gets the actual maximum value plotted on the chart.
- /// </summary>
- public DateTime? ActualMinimum
- {
- get { return (DateTime?)GetValue(ActualMinimumProperty); }
- private set { SetValue(ActualMinimumProperty, value); }
- }
- /// <summary>
- /// Identifies the ActualMinimum dependency property.
- /// </summary>
- public static readonly DependencyProperty ActualMinimumProperty =
- DependencyProperty.Register(
- "ActualMinimum",
- typeof(DateTime?),
- typeof(DateTimeAxis),
- null);
- #endregion public DateTime? ActualMinimum
- #region public DateTime? Maximum
- /// <summary>
- /// Gets or sets the maximum value plotted on the axis.
- /// </summary>
- [TypeConverter(typeof(NullableConverter<DateTime>))]
- public DateTime? Maximum
- {
- get { return (DateTime?)GetValue(MaximumProperty); }
- set { SetValue(MaximumProperty, value); }
- }
- /// <summary>
- /// Identifies the Maximum dependency property.
- /// </summary>
- public static readonly DependencyProperty MaximumProperty =
- DependencyProperty.Register(
- "Maximum",
- typeof(DateTime?),
- typeof(DateTimeAxis),
- new PropertyMetadata(null, OnMaximumPropertyChanged));
- /// <summary>
- /// MaximumProperty property changed handler.
- /// </summary>
- /// <param name="d">DateTimeAxis2 that changed its Maximum.</param>
- /// <param name="e">Event arguments.</param>
- private static void OnMaximumPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- DateTimeAxis source = (DateTimeAxis)d;
- DateTime? newValue = (DateTime?)e.NewValue;
- source.OnMaximumPropertyChanged(newValue);
- }
- /// <summary>
- /// MaximumProperty property changed handler.
- /// </summary>
- /// <param name="newValue">New value.</param>
- private void OnMaximumPropertyChanged(DateTime? newValue)
- {
- this.ProtectedMaximum = newValue;
- }
- #endregion public DateTime? Maximum
- #region public DateTime? Minimum
- /// <summary>
- /// Gets or sets the minimum value to plot on the axis.
- /// </summary>
- [TypeConverter(typeof(NullableConverter<DateTime>))]
- public DateTime? Minimum
- {
- get { return (DateTime?)GetValue(MinimumProperty); }
- set { SetValue(MinimumProperty, value); }
- }
- /// <summary>
- /// Identifies the Minimum dependency property.
- /// </summary>
- public static readonly DependencyProperty MinimumProperty =
- DependencyProperty.Register(
- "Minimum",
- typeof(DateTime?),
- typeof(DateTimeAxis),
- new PropertyMetadata(null, OnMinimumPropertyChanged));
- /// <summary>
- /// MinimumProperty property changed handler.
- /// </summary>
- /// <param name="d">DateTimeAxis2 that changed its Minimum.</param>
- /// <param name="e">Event arguments.</param>
- private static void OnMinimumPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- DateTimeAxis source = (DateTimeAxis)d;
- DateTime? newValue = (DateTime?)e.NewValue;
- source.OnMinimumPropertyChanged(newValue);
- }
- /// <summary>
- /// MinimumProperty property changed handler.
- /// </summary>
- /// <param name="newValue">New value.</param>
- private void OnMinimumPropertyChanged(DateTime? newValue)
- {
- this.ProtectedMinimum = newValue;
- }
- #endregion public DateTime? Minimum
- #region public double? Interval
- /// <summary>
- /// Gets or sets the axis interval.
- /// </summary>
- [TypeConverter(typeof(NullableConverter<double>))]
- public double? Interval
- {
- get { return (double?)GetValue(IntervalProperty); }
- set { SetValue(IntervalProperty, value); }
- }
- /// <summary>
- /// Identifies the Interval dependency property.
- /// </summary>
- public static readonly DependencyProperty IntervalProperty =
- DependencyProperty.Register(
- "Interval",
- typeof(double?),
- typeof(DateTimeAxis),
- new PropertyMetadata(null, OnIntervalPropertyChanged));
- /// <summary>
- /// IntervalProperty property changed handler.
- /// </summary>
- /// <param name="d">DateTimeAxis2 that changed its Interval.</param>
- /// <param name="e">Event arguments.</param>
- private static void OnIntervalPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- DateTimeAxis source = (DateTimeAxis)d;
- source.OnIntervalPropertyChanged();
- }
- /// <summary>
- /// IntervalProperty property changed handler.
- /// </summary>
- private void OnIntervalPropertyChanged()
- {
- Invalidate();
- }
- #endregion public double? Interval
- #region public double ActualInterval
- /// <summary>
- /// Gets the actual interval.
- /// </summary>
- public double ActualInterval
- {
- get { return (double)GetValue(ActualIntervalProperty); }
- private set { SetValue(ActualIntervalProperty, value); }
- }
- /// <summary>
- /// Identifies the ActualInterval dependency property.
- /// </summary>
- public static readonly DependencyProperty ActualIntervalProperty =
- DependencyProperty.Register(
- "ActualInterval",
- typeof(double),
- typeof(DateTimeAxis),
- new PropertyMetadata(double.NaN));
- #endregion public double ActualInterval
- #region public DateTimeIntervalType IntervalType
- /// <summary>
- /// Gets or sets the interval to use for the axis.
- /// </summary>
- public ExtendedDateTimeIntervalType IntervalType
- {
- get { return (ExtendedDateTimeIntervalType)GetValue(IntervalTypeProperty); }
- set { SetValue(IntervalTypeProperty, value); }
- }
- /// <summary>
- /// Identifies the InternalIntervalType dependency property.
- /// </summary>
- public static readonly DependencyProperty IntervalTypeProperty =
- DependencyProperty.Register(
- "IntervalType",
- typeof(ExtendedDateTimeIntervalType),
- typeof(DateTimeAxis),
- new PropertyMetadata(ExtendedDateTimeIntervalType.Auto, OnIntervalTypePropertyChanged));
- /// <summary>
- /// IntervalTypeProperty property changed handler.
- /// </summary>
- /// <param name="d">DateTimeAxis that changed its InternalIntervalType.</param>
- /// <param name="e">Event arguments.</param>
- private static void OnIntervalTypePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- DateTimeAxis source = (DateTimeAxis)d;
- ExtendedDateTimeIntervalType newValue = (ExtendedDateTimeIntervalType)e.NewValue;
- source.OnIntervalTypePropertyChanged(newValue);
- }
- /// <summary>
- /// IntervalTypeProperty property changed handler.
- /// </summary>
- /// <param name="newValue">New value.</param>
- private void OnIntervalTypePropertyChanged(ExtendedDateTimeIntervalType newValue)
- {
- this.ActualIntervalType = newValue;
- Invalidate();
- }
- #endregion public DateTimeIntervalType IntervalType
- #region public DateTimeIntervalType ActualIntervalType
- /// <summary>
- /// Gets or sets the actual interval type.
- /// </summary>
- private ExtendedDateTimeIntervalType ActualIntervalType
- {
- get { return (ExtendedDateTimeIntervalType)GetValue(ActualIntervalTypeProperty); }
- set { SetValue(ActualIntervalTypeProperty, value); }
- }
- /// <summary>
- /// Identifies the ActualIntervalType dependency property.
- /// </summary>
- private static readonly DependencyProperty ActualIntervalTypeProperty =
- DependencyProperty.Register(
- "ActualIntervalType",
- typeof(ExtendedDateTimeIntervalType),
- typeof(DateTimeAxis),
- new PropertyMetadata(ExtendedDateTimeIntervalType.Auto));
- #endregion public DateTimeIntervalType ActualIntervalType
- /// <summary>
- /// Gets the origin value on the axis.
- /// </summary>
- protected override IComparable Origin
- {
- get { return null; }
- }
- /// <summary>
- /// Instantiates a new instance of the DateTimeAxis2 class.
- /// </summary>
- public DateTimeAxis()
- {
- int year = DateTime.Now.Year;
- this.ActualRange = new Range<IComparable>(new DateTime(year, 1, 1), new DateTime(year + 1, 1, 1));
- }
- /// <summary>
- /// Creates a new instance of the DateTimeAxisLabel class.
- /// </summary>
- /// <returns>Returns a new instance of the DateTimeAxisLabel class.
- /// </returns>
- protected override Control CreateAxisLabel()
- {
- return new DateTimeAxisLabel();
- }
- /// <summary>
- /// Prepares an instance of the DateTimeAxisLabel class by setting its
- /// IntervalType property.
- /// </summary>
- /// <param name="label">An instance of the DateTimeAxisLabel class.
- /// </param>
- /// <param name="dataContext">The data context to assign to the label.
- /// </param>
- protected override void PrepareAxisLabel(Control label, object dataContext)
- {
- DateTimeAxisLabel dateTimeAxisLabel = label as DateTimeAxisLabel;
- if (dateTimeAxisLabel != null)
- {
- if (ActualIntervalType == ExtendedDateTimeIntervalType.OddDays)
- dateTimeAxisLabel.IntervalType = DateTimeIntervalType.Days;
- else
- dateTimeAxisLabel.IntervalType = (DateTimeIntervalType)(int)ActualIntervalType;
- }
- base.PrepareAxisLabel(label, dataContext);
- }
- /// <summary>
- /// Gets the actual range of DateTime values.
- /// </summary>
- protected Range<DateTime> ActualDateTimeRange { get; private set; }
- /// <summary>
- /// Updates the typed actual maximum and minimum properties when the
- /// actual range changes.
- /// </summary>
- /// <param name="range">The actual range.</param>
- protected override void OnActualRangeChanged(Range<IComparable> range)
- {
- ActualDateTimeRange = range.ToDateTimeRange();
- if (range.HasData)
- {
- this.ActualMaximum = (DateTime)range.Maximum;
- this.ActualMinimum = (DateTime)range.Minimum;
- }
- else
- {
- this.ActualMaximum = null;
- this.ActualMinimum = null;
- }
- base.OnActualRangeChanged(range);
- }
- /// <summary>
- /// Returns a value indicating whether a value can plot.
- /// </summary>
- /// <param name="value">The value to plot.</param>
- /// <returns>A value indicating whether a value can plot.</returns>
- public override bool CanPlot(object value)
- {
- DateTime val;
- return ValueHelper.TryConvert(value, out val);
- }
- /// <summary>
- /// Returns the plot area coordinate of a value.
- /// </summary>
- /// <param name="value">The value to plot.</param>
- /// <param name="length">The length of the axis.</param>
- /// <returns>The plot area coordinate of a value.</returns>
- protected override UnitValue GetPlotAreaCoordinate(object value, double length)
- {
- return GetPlotAreaCoordinate(value, ActualDateTimeRange, length);
- }
- /// <summary>
- /// Returns the plot area coordinate of a value.
- /// </summary>
- /// <param name="value">The value to plot.</param>
- /// <param name="currentRange">The range to use determine the coordinate.</param>
- /// <param name="length">The length of the axis.</param>
- /// <returns>The plot area coordinate of a value.</returns>
- protected override UnitValue GetPlotAreaCoordinate(object value, Range<IComparable> currentRange, double length)
- {
- return GetPlotAreaCoordinate(value, currentRange.ToDateTimeRange(), length);
- }
- /// <summary>
- /// Returns the plot area coordinate of a value.
- /// </summary>
- /// <param name="value">The value to plot.</param>
- /// <param name="currentRange">The range to use determine the coordinate.</param>
- /// <param name="length">The length of the axis.</param>
- /// <returns>The plot area coordinate of a value.</returns>
- private static UnitValue GetPlotAreaCoordinate(object value, Range<DateTime> currentRange, double length)
- {
- if (currentRange.HasData)
- {
- DateTime dateTimeValue = ValueHelper.ToDateTime(value);
- double rangelength = currentRange.Maximum.ToOADate() - currentRange.Minimum.ToOADate();
- double pixelLength = Math.Max(length - 1, 0);
- return new UnitValue((dateTimeValue.ToOADate() - currentRange.Minimum.ToOADate()) * (pixelLength / rangelength), Unit.Pixels);
- }
- return UnitValue.NaN();
- }
- /// <summary>
- /// Returns the actual interval to use to determine which values are
- /// displayed in the axis.
- /// </summary>
- /// <param name="availableSize">The available size.</param>
- /// <returns>The actual interval to use to determine which values are
- /// displayed in the axis.
- /// </returns>
- private double CalculateActualInterval(Size availableSize)
- {
- if (Interval != null)
- {
- return Interval.Value;
- }
- ExtendedDateTimeIntervalType intervalType;
- double interval = CalculateDateTimeInterval(ActualDateTimeRange.Minimum, ActualDateTimeRange.Maximum, out intervalType, availableSize);
- ActualIntervalType = intervalType;
- return interval;
- }
- /// <summary>
- /// Returns a sequence of major values.
- /// </summary>
- /// <param name="availableSize">The available size.</param>
- /// <returns>A sequence of major values.</returns>
- protected virtual IEnumerable<DateTime> GetMajorAxisValues(Size availableSize)
- {
- if (!ActualRange.HasData || ValueHelper.Compare(ActualRange.Minimum, ActualRange.Maximum) == 0 || GetLength(availableSize) == 0.0)
- {
- yield break;
- }
- this.ActualInterval = CalculateActualInterval(availableSize);
- DateTime date = ActualDateTimeRange.Minimum;
- DateTime start = AlignIntervalStart(date, this.ActualInterval, ActualIntervalType);
- while (start < date)
- {
- start = IncrementDateTime(start, this.ActualInterval);
- }
- IEnumerable<DateTime> intermediateDates =
- EnumerableFunctions
- .Iterate(start, next => IncrementDateTime(next, this.ActualInterval))
- .TakeWhile(current => ActualDateTimeRange.Contains(current));
- foreach (DateTime current in intermediateDates)
- {
- yield return current;
- }
- }
- /// <summary>
- /// Returns a sequence of values to create major tick marks for.
- /// </summary>
- /// <param name="availableSize">The available size.</param>
- /// <returns>A sequence of values to create major tick marks for.
- /// </returns>
- protected override IEnumerable<IComparable> GetMajorTickMarkValues(Size availableSize)
- {
- return GetMajorAxisValues(availableSize).CastWrapper<IComparable>();
- }
- /// <summary>
- /// Returns a sequence of values to plot on the axis.
- /// </summary>
- /// <param name="availableSize">The available size.</param>
- /// <returns>A sequence of values to plot on the axis.</returns>
- protected override IEnumerable<IComparable> GetLabelValues(Size availableSize)
- {
- return GetMajorAxisValues(availableSize).CastWrapper<IComparable>();
- }
- /// <summary>
- /// This method accepts a date time and increments it.
- /// </summary>
- /// <param name="date">A date time.</param>
- /// <param name="interval">The interval used to increment the date time.
- /// </param>
- /// <returns>The new date time.</returns>
- private DateTime IncrementDateTime(DateTime date, double interval)
- {
- ExtendedDateTimeIntervalType intervalType = this.ActualIntervalType;
- TimeSpan span = new TimeSpan(0);
- DateTime result;
- if (intervalType == ExtendedDateTimeIntervalType.Days)
- {
- span = TimeSpan.FromDays(interval);
- }
- else if (intervalType == ExtendedDateTimeIntervalType.Hours)
- {
- span = TimeSpan.FromHours(interval);
- }
- else if (intervalType == ExtendedDateTimeIntervalType.Milliseconds)
- {
- span = TimeSpan.FromMilliseconds(interval);
- }
- else if (intervalType == ExtendedDateTimeIntervalType.Seconds)
- {
- span = TimeSpan.FromSeconds(interval);
- }
- else if (intervalType == ExtendedDateTimeIntervalType.Minutes)
- {
- span = TimeSpan.FromMinutes(interval);
- }
- else if (intervalType == ExtendedDateTimeIntervalType.Weeks)
- {
- span = TimeSpan.FromDays(7.0 * interval);
- }
- else if (intervalType == ExtendedDateTimeIntervalType.Months)
- {
- // Special case handling when current date point
- // to the last day of the month
- bool lastMonthDay = false;
- if (date.Day == DateTime.DaysInMonth(date.Year, date.Month))
- {
- lastMonthDay = true;
- }
- // Add specified amount of months
- date = date.AddMonths((int)Math.Floor(interval));
- span = TimeSpan.FromDays(30.0 * (interval - Math.Floor(interval)));
- // Check if last month of the day was used
- if (lastMonthDay && span.Ticks == 0)
- {
- // Make sure the last day of the month is selected
- int daysInMobth = DateTime.DaysInMonth(date.Year, date.Month);
- date = date.AddDays(daysInMobth - date.Day);
- }
- }
- else if (intervalType == ExtendedDateTimeIntervalType.Years)
- {
- date = date.AddYears((int)Math.Floor(interval));
- span = TimeSpan.FromDays(365.0 * (interval - Math.Floor(interval)));
- }
- if (this.IntervalType == ExtendedDateTimeIntervalType.OddDays)
- {
- DateTime newDate;
- if(span != TimeSpan.Zero)
- newDate = date.Add(span);
- else newDate = date.AddDays(interval);
- while (newDate.Day % 2 != 1)
- newDate = newDate.AddDays(1);
- span = newDate - date;
- }
- result = date.Add(span);
- return result;
- }
- /// <summary>
- /// Adjusts the beginning of the first interval depending on the type and size.
- /// </summary>
- /// <param name="start">Original start point.</param>
- /// <param name="intervalSize">Interval size.</param>
- /// <param name="type">Type of the interval (Month, Year, ...).</param>
- /// <returns>
- /// Adjusted interval start position.
- /// </returns>
- private static DateTime AlignIntervalStart(DateTime start, double intervalSize, ExtendedDateTimeIntervalType type)
- {
- // Do not adjust start position for these interval type
- if (type == ExtendedDateTimeIntervalType.Auto)
- {
- return start;
- }
- // Get the beginning of the interval depending on type
- DateTime newStartDate = start;
- // Adjust the months interval depending on size
- if (intervalSize > 0.0 && intervalSize != 1.0)
- {
- if (type == ExtendedDateTimeIntervalType.Months && intervalSize <= 12.0 && intervalSize > 1)
- {
- // Make sure that the beginning is aligned correctly for cases
- // like quarters and half years
- DateTime resultDate = newStartDate;
- DateTime sizeAdjustedDate = new DateTime(newStartDate.Year, 1, 1, 0, 0, 0);
- while (sizeAdjustedDate < newStartDate)
- {
- resultDate = sizeAdjustedDate;
- sizeAdjustedDate = sizeAdjustedDate.AddMonths((int)intervalSize);
- }
- newStartDate = resultDate;
- return newStartDate;
- }
- }
- // Check interval type
- switch (type)
- {
- case ExtendedDateTimeIntervalType.Years:
- int year = (int)((int)(newStartDate.Year / intervalSize) * intervalSize);
- if (year <= 0)
- {
- year = 1;
- }
- newStartDate = new DateTime(year, 1, 1, 0, 0, 0);
- break;
- case ExtendedDateTimeIntervalType.Months:
- int month = (int)((int)(newStartDate.Month / intervalSize) * intervalSize);
- if (month <= 0)
- {
- month = 1;
- }
- newStartDate = new DateTime(newStartDate.Year, month, 1, 0, 0, 0);
- break;
- case ExtendedDateTimeIntervalType.Days:
- case ExtendedDateTimeIntervalType.OddDays:
- int day = (int)((int)(newStartDate.Day / intervalSize) * intervalSize);
- if (day <= 0)
- {
- day = 1;
- }
- newStartDate = new DateTime(newStartDate.Year, newStartDate.Month, day, 0, 0, 0);
- break;
- case ExtendedDateTimeIntervalType.Hours:
- int hour = (int)((int)(newStartDate.Hour / intervalSize) * intervalSize);
- newStartDate = new DateTime(
- newStartDate.Year,
- newStartDate.Month,
- newStartDate.Day,
- hour,
- 0,
- 0);
- break;
- case ExtendedDateTimeIntervalType.Minutes:
- int minute = (int)((int)(newStartDate.Minute / intervalSize) * intervalSize);
- newStartDate = new DateTime(
- newStartDate.Year,
- newStartDate.Month,
- newStartDate.Day,
- newStartDate.Hour,
- minute,
- 0);
- break;
- case ExtendedDateTimeIntervalType.Seconds:
- int second = (int)((int)(newStartDate.Second / intervalSize) * intervalSize);
- newStartDate = new DateTime(
- newStartDate.Year,
- newStartDate.Month,
- newStartDate.Day,
- newStartDate.Hour,
- newStartDate.Minute,
- second,
- 0);
- break;
- case ExtendedDateTimeIntervalType.Milliseconds:
- int milliseconds = (int)((int)(newStartDate.Millisecond / intervalSize) * intervalSize);
- newStartDate = new DateTime(
- newStartDate.Year,
- newStartDate.Month,
- newStartDate.Day,
- newStartDate.Hour,
- newStartDate.Minute,
- newStartDate.Second,
- milliseconds);
- break;
- case ExtendedDateTimeIntervalType.Weeks:
- // Elements that have interval set to weeks should be aligned to the
- // nearest start of week no matter how many weeks is the interval.
- newStartDate = new DateTime(
- newStartDate.Year,
- newStartDate.Month,
- newStartDate.Day,
- 0,
- 0,
- 0);
- newStartDate = newStartDate.AddDays(-((int)newStartDate.DayOfWeek));
- break;
- }
- return newStartDate;
- }
- /// <summary>
- /// Returns the value range given a plot area coordinate.
- /// </summary>
- /// <param name="value">The position.</param>
- /// <returns>A range of values at that plot area coordinate.</returns>
- protected override IComparable GetValueAtPosition(UnitValue value)
- {
- if (ActualRange.HasData && ActualLength != 0.0)
- {
- double coordinate = value.Value;
- if (value.Unit == Unit.Pixels)
- {
- double minimumAsDouble = ActualDateTimeRange.Minimum.ToOADate();
- double rangelength = ActualDateTimeRange.Maximum.ToOADate() - minimumAsDouble;
- DateTime output = DateTime.FromOADate((coordinate * (rangelength / ActualLength)) + minimumAsDouble);
- return output;
- }
- else
- {
- throw new NotImplementedException();
- }
- }
- return null;
- }
- /// <summary>
- /// Recalculates a DateTime interval obtained from maximum and minimum.
- /// </summary>
- /// <param name="minimum">The minimum.</param>
- /// <param name="maximum">The maximum.</param>
- /// <param name="type">Date time interval type.</param>
- /// <param name="availableSize">The available size.</param>
- /// <returns>Auto Interval.</returns>
- [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "The method should inspect all variations of time span (millisec to year) and contains long case. Otherwise is simple and readable.")]
- private double CalculateDateTimeInterval(DateTime minimum, DateTime maximum, out ExtendedDateTimeIntervalType type, Size availableSize)
- {
- DateTime dateTimeMin = minimum;
- DateTime dateTimeMax = maximum;
- TimeSpan timeSpan = dateTimeMax.Subtract(dateTimeMin);
- // this algorithm is designed to return close to 10 intervals.
- // we need to align the time span for PrefferedNumberOfIntervals
- double maxIntervals = Orientation == AxisOrientation.X ? MaximumAxisIntervalsPer200Pixels * 0.8 : MaximumAxisIntervalsPer200Pixels;
- double rangeMultiplicator = GetLength(availableSize) / (200 * 10 / maxIntervals);
- timeSpan = new TimeSpan((long)((double)timeSpan.Ticks / rangeMultiplicator));
- // Minutes
- double inter = timeSpan.TotalMinutes;
- // For Range less than 60 seconds interval is 5 sec
- if (inter <= 1.0)
- {
- // Milli Seconds
- double milliSeconds = timeSpan.TotalMilliseconds;
- if (milliSeconds <= 10)
- {
- type = ExtendedDateTimeIntervalType.Milliseconds;
- return 1;
- }
- if (milliSeconds <= 50)
- {
- type = ExtendedDateTimeIntervalType.Milliseconds;
- return 4;
- }
- if (milliSeconds <= 200)
- {
- type = ExtendedDateTimeIntervalType.Milliseconds;
- return 20;
- }
- if (milliSeconds <= 500)
- {
- type = ExtendedDateTimeIntervalType.Milliseconds;
- return 50;
- }
- // Seconds
- double seconds = timeSpan.TotalSeconds;
- if (seconds <= 7)
- {
- type = ExtendedDateTimeIntervalType.Seconds;
- return 1;
- }
- else if (seconds <= 15)
- {
- type = ExtendedDateTimeIntervalType.Seconds;
- return 2;
- }
- else if (seconds <= 30)
- {
- type = ExtendedDateTimeIntervalType.Seconds;
- return 5;
- }
- else if (seconds <= 60)
- {
- type = ExtendedDateTimeIntervalType.Seconds;
- return 10;
- }
- }
- else if (inter <= 2.0)
- {
- // For Range less than 120 seconds interval is 10 sec
- type = ExtendedDateTimeIntervalType.Seconds;
- return 20;
- }
- else if (inter <= 3.0)
- {
- // For Range less than 180 seconds interval is 30 sec
- type = ExtendedDateTimeIntervalType.Seconds;
- return 30;
- }
- else if (inter <= 10)
- {
- // For Range less than 10 minutes interval is 1 min
- type = ExtendedDateTimeIntervalType.Minutes;
- return 1;
- }
- else if (inter <= 20)
- {
- // For Range less than 20 minutes interval is 1 min
- type = ExtendedDateTimeIntervalType.Minutes;
- return 2;
- }
- else if (inter <= 60)
- {
- // For Range less than 60 minutes interval is 5 min
- type = ExtendedDateTimeIntervalType.Minutes;
- return 5;
- }
- else if (inter <= 120)
- {
- // For Range less than 120 minutes interval is 10 min
- type = ExtendedDateTimeIntervalType.Minutes;
- return 10;
- }
- else if (inter <= 180)
- {
- // For Range less than 180 minutes interval is 30 min
- type = ExtendedDateTimeIntervalType.Minutes;
- return 30;
- }
- else if (inter <= 60 * 12)
- {
- // For Range less than 12 hours interval is 1 hour
- type = ExtendedDateTimeIntervalType.Hours;
- return 1;
- }
- else if (inter <= 60 * 24)
- {
- // For Range less than 24 hours interval is 4 hour
- type = ExtendedDateTimeIntervalType.Hours;
- return 4;
- }
- else if (inter <= 60 * 24 * 2)
- {
- // For Range less than 2 days interval is 6 hour
- type = ExtendedDateTimeIntervalType.Hours;
- return 6;
- }
- else if (inter <= 60 * 24 * 3)
- {
- // For Range less than 3 days interval is 12 hour
- type = ExtendedDateTimeIntervalType.Hours;
- return 12;
- }
- else if (inter <= 60 * 24 * 10)
- {
- // For Range less than 10 days interval is 1 day
- type = ExtendedDateTimeIntervalType.Days;
- return 1;
- }
- else if (inter <= 60 * 24 * 20)
- {
- // For Range less than 20 days interval is 2 day
- type = ExtendedDateTimeIntervalType.Days;
- return 2;
- }
- else if (inter <= 60 * 24 * 30)
- {
- // For Range less than 30 days interval is 3 day
- type = ExtendedDateTimeIntervalType.Days;
- return 3;
- }
- else if (inter <= 60 * 24 * 30.5 * 2)
- {
- // For Range less than 2 months interval is 1 week
- type = ExtendedDateTimeIntervalType.Weeks;
- return 1;
- }
- else if (inter <= 60 * 24 * 30.5 * 5)
- {
- // For Range less than 5 months interval is 2weeks
- type = ExtendedDateTimeIntervalType.Weeks;
- return 2;
- }
- else if (inter <= 60 * 24 * 30.5 * 12)
- {
- // For Range less than 12 months interval is 1 month
- type = ExtendedDateTimeIntervalType.Months;
- return 1;
- }
- else if (inter <= 60 * 24 * 30.5 * 24)
- {
- // For Range less than 24 months interval is 3 month
- type = ExtendedDateTimeIntervalType.Months;
- return 3;
- }
- else if (inter <= 60 * 24 * 30.5 * 48)
- {
- // For Range less than 48 months interval is 6 months
- type = ExtendedDateTimeIntervalType.Months;
- return 6;
- }
- // For Range more than 48 months interval is year
- type = ExtendedDateTimeIntervalType.Years;
- double years = inter / 60 / 24 / 365;
- if (years < 5)
- {
- return 1;
- }
- else if (years < 10)
- {
- return 2;
- }
- // Make a correction of the interval
- return Math.Floor(years / 5);
- }
- /// <summary>
- /// Overrides the actual range to ensure that it is never set to an
- /// empty range.
- /// </summary>
- /// <param name="range">The range to override.</param>
- /// <returns>The overridden range.</returns>
- [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "This method is very difficult to break up cleanly.")]
- protected override Range<IComparable> OverrideDataRange(Range<IComparable> range)
- {
- Range<IComparable> overriddenActualRange = range;
- if (!overriddenActualRange.HasData)
- {
- int year = DateTime.Now.Year;
- return new Range<IComparable>(new DateTime(year, 1, 1), new DateTime(year + 1, 1, 1));
- }
- else if (ValueHelper.Compare(overriddenActualRange.Minimum, overriddenActualRange.Maximum) == 0)
- {
- DateTime minimum = ValueHelper.ToDateTime(overriddenActualRange.Minimum);
- DateTime midpoint = ((DateTime.MinValue == minimum) ? DateTime.Now : minimum).Date;
- return new Range<IComparable>(midpoint.AddMonths(-6), midpoint.AddMonths(6));
- }
- //// ActualLength of 1.0 or less maps all points to the same coordinate
- //if (range.HasData && this.ActualLength > 1.0)
- //{
- // IList<ValueMarginCoordinateAndOverlap> valueMargins = new List<ValueMarginCoordinateAndOverlap>();
- // foreach (ValueMargin valueMargin in
- // this.RegisteredListeners
- // .OfType<IValueMarginProvider>()
- // .SelectMany(provider => provider.GetValueMargins(this)))
- // {
- // valueMargins.Add(
- // new ValueMarginCoordinateAndOverlap
- // {
- // ValueMargin = valueMargin,
- // });
- // }
- // if (valueMargins.Count > 0)
- // {
- // double maximumPixelMarginLength =
- // valueMargins
- // .Select(valueMargin => valueMargin.ValueMargin.LowMargin + valueMargin.ValueMargin.HighMargin)
- // .MaxOrNullable().Value;
- // // Requested margin is larger than the axis so give up
- // // trying to find a range that will fit it.
- // if (maximumPixelMarginLength > this.ActualLength)
- // {
- // return range;
- // }
- // Range<DateTime> currentRange = range.ToDateTimeRange();
- // // Ensure range is not empty.
- // if (currentRange.Minimum == currentRange.Maximum)
- // {
- // int year = DateTime.Now.Year;
- // currentRange = new Range<DateTime>(new DateTime(year, 1, 1), new DateTime(year + 1, 1, 1));
- // }
- // // priming the loop
- // double actualLength = this.ActualLength;
- // ValueMarginCoordinateAndOverlap maxLeftOverlapValueMargin;
- // ValueMarginCoordinateAndOverlap maxRightOverlapValueMargin;
- // UpdateValueMargins(valueMargins, currentRange.ToComparableRange());
- // GetMaxLeftAndRightOverlap(valueMargins, out maxLeftOverlapValueMargin, out maxRightOverlapValueMargin);
- // while (maxLeftOverlapValueMargin.LeftOverlap > 0 || maxRightOverlapValueMargin.RightOverlap > 0)
- // {
- // long unitOverPixels = currentRange.GetLength().Value.Ticks / ((long) actualLength);
- // DateTime newMinimum = new DateTime(currentRange.Minimum.Ticks - (long)((maxLeftOverlapValueMargin.LeftOverlap + 0.5) * unitOverPixels));
- // DateTime newMaximum = new DateTime(currentRange.Maximum.Ticks + (long)((maxRightOverlapValueMargin.RightOverlap + 0.5) * unitOverPixels));
- // currentRange = new Range<DateTime>(newMinimum, newMaximum);
- // UpdateValueMargins(valueMargins, currentRange.ToComparableRange());
- // GetMaxLeftAndRightOverlap(valueMargins, out maxLeftOverlapValueMargin, out maxRightOverlapValueMargin);
- // }
- // return currentRange.ToComparableRange();
- // }
- //}
- return range;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement