/Main/src/DynamicDataDisplay/Charts/Axes/DateTime/TimePeriodTicksProvider.cs
C# | 269 lines | 227 code | 42 blank | 0 comment | 31 complexity | 054b8516de9405c9f146f9c0d261b0ff MD5 | raw file
Possible License(s): CC-BY-SA-3.0
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary;
-
- namespace Microsoft.Research.DynamicDataDisplay.Charts
- {
- internal abstract class TimePeriodTicksProvider<T> : ITicksProvider<T>
- {
- public event EventHandler Changed;
- protected void RaiseChanged()
- {
- if (Changed != null)
- {
- Changed(this, EventArgs.Empty);
- }
- }
-
- protected abstract T RoundUp(T time, DifferenceIn diff);
- protected abstract T RoundDown(T time, DifferenceIn diff);
-
- private bool differenceInited = false;
- private DifferenceIn difference;
- protected DifferenceIn Difference
- {
- get
- {
- if (!differenceInited)
- {
- difference = GetDifferenceCore();
- differenceInited = true;
- }
- return difference;
- }
- }
- protected abstract DifferenceIn GetDifferenceCore();
-
- private int[] tickCounts = null;
- protected int[] TickCounts
- {
- get
- {
- if (tickCounts == null)
- tickCounts = GetTickCountsCore();
- return tickCounts;
- }
- }
- protected abstract int[] GetTickCountsCore();
-
- public int DecreaseTickCount(int ticksCount)
- {
- if (ticksCount > TickCounts[0]) return TickCounts[0];
-
- for (int i = 0; i < TickCounts.Length; i++)
- if (ticksCount > TickCounts[i])
- return TickCounts[i];
-
- return TickCounts.Last();
- }
-
- public int IncreaseTickCount(int ticksCount)
- {
- if (ticksCount >= TickCounts[0]) return TickCounts[0];
-
- for (int i = TickCounts.Length - 1; i >= 0; i--)
- if (ticksCount < TickCounts[i])
- return TickCounts[i];
-
- return TickCounts.Last();
- }
-
- protected abstract int GetSpecificValue(T start, T dt);
- protected abstract T GetStart(T start, int value, int step);
- protected abstract bool IsMinDate(T dt);
- protected abstract T AddStep(T dt, int step);
-
- public ITicksInfo<T> GetTicks(Range<T> range, int ticksCount)
- {
- T start = range.Min;
- T end = range.Max;
- DifferenceIn diff = Difference;
- start = RoundDown(start, end);
- end = RoundUp(start, end);
-
- RoundingInfo bounds = RoundingHelper.CreateRoundedRange(
- GetSpecificValue(start, start),
- GetSpecificValue(start, end));
-
- int delta = (int)(bounds.Max - bounds.Min);
- if (delta == 0)
- return new TicksInfo<T> { Ticks = new T[] { start } };
-
- int step = delta / ticksCount;
-
- if (step == 0) step = 1;
-
- T tick = GetStart(start, (int)bounds.Min, step);
- bool isMinDateTime = IsMinDate(tick) && step != 1;
- if (isMinDateTime)
- step--;
-
- List<T> ticks = new List<T>();
- T finishTick = AddStep(range.Max, step);
- while (Continue(tick, finishTick))
- {
- ticks.Add(tick);
- tick = AddStep(tick, step);
- if (isMinDateTime)
- {
- isMinDateTime = false;
- step++;
- }
- }
-
- ticks = Trim(ticks, range);
-
- TicksInfo<T> res = new TicksInfo<T> { Ticks = ticks.ToArray(), Info = diff };
- return res;
- }
-
- protected abstract bool Continue(T current, T end);
-
- protected abstract T RoundUp(T start, T end);
-
- protected abstract T RoundDown(T start, T end);
-
- protected abstract List<T> Trim(List<T> ticks, Range<T> range);
-
- public ITicksProvider<T> MinorProvider
- {
- get { throw new NotSupportedException(); }
- }
-
- public ITicksProvider<T> MajorProvider
- {
- get { throw new NotSupportedException(); }
- }
- }
-
- internal abstract class DatePeriodTicksProvider : TimePeriodTicksProvider<DateTime>
- {
- protected sealed override bool Continue(DateTime current, DateTime end)
- {
- return current < end;
- }
-
- protected sealed override List<DateTime> Trim(List<DateTime> ticks, Range<DateTime> range)
- {
- int startIndex = 0;
- for (int i = 0; i < ticks.Count - 1; i++)
- {
- if (ticks[i] <= range.Min && range.Min <= ticks[i + 1])
- {
- startIndex = i;
- break;
- }
- }
-
- int endIndex = ticks.Count - 1;
- for (int i = ticks.Count - 1; i >= 1; i--)
- {
- if (ticks[i] >= range.Max && range.Max > ticks[i - 1])
- {
- endIndex = i;
- break;
- }
- }
-
- List<DateTime> res = new List<DateTime>(endIndex - startIndex + 1);
- for (int i = startIndex; i <= endIndex; i++)
- {
- res.Add(ticks[i]);
- }
-
- return res;
- }
-
- protected sealed override DateTime RoundUp(DateTime start, DateTime end)
- {
- bool isPositive = (end - start).Ticks > 0;
- return isPositive ? SafelyRoundUp(end) : RoundDown(end, Difference);
- }
-
- private DateTime SafelyRoundUp(DateTime dt)
- {
- if (AddStep(dt, 1) == DateTime.MaxValue)
- return DateTime.MaxValue;
-
- return RoundUp(dt, Difference);
- }
-
- protected sealed override DateTime RoundDown(DateTime start, DateTime end)
- {
- bool isPositive = (end - start).Ticks > 0;
- return isPositive ? RoundDown(start, Difference) : SafelyRoundUp(start);
- }
-
- protected sealed override DateTime RoundDown(DateTime time, DifferenceIn diff)
- {
- DateTime res = time;
-
- switch (diff)
- {
- case DifferenceIn.Year:
- res = new DateTime(time.Year, 1, 1);
- break;
- case DifferenceIn.Month:
- res = new DateTime(time.Year, time.Month, 1);
- break;
- case DifferenceIn.Day:
- res = time.Date;
- break;
- case DifferenceIn.Hour:
- res = time.Date.AddHours(time.Hour);
- break;
- case DifferenceIn.Minute:
- res = time.Date.AddHours(time.Hour).AddMinutes(time.Minute);
- break;
- case DifferenceIn.Second:
- res = time.Date.AddHours(time.Hour).AddMinutes(time.Minute).AddSeconds(time.Second);
- break;
- case DifferenceIn.Millisecond:
- res = time.Date.AddHours(time.Hour).AddMinutes(time.Minute).AddSeconds(time.Second).AddMilliseconds(time.Millisecond);
- break;
- default:
- break;
- }
-
- DebugVerify.Is(res <= time);
-
- return res;
- }
-
- protected override DateTime RoundUp(DateTime dateTime, DifferenceIn diff)
- {
- DateTime res = RoundDown(dateTime, diff);
-
- switch (diff)
- {
- case DifferenceIn.Year:
- res = res.AddYears(1);
- break;
- case DifferenceIn.Month:
- res = res.AddMonths(1);
- break;
- case DifferenceIn.Day:
- res = res.AddDays(1);
- break;
- case DifferenceIn.Hour:
- res = res.AddHours(1);
- break;
- case DifferenceIn.Minute:
- res = res.AddMinutes(1);
- break;
- case DifferenceIn.Second:
- res = res.AddSeconds(1);
- break;
- case DifferenceIn.Millisecond:
- res = res.AddMilliseconds(1);
- break;
- default:
- break;
- }
-
- return res;
- }
- }
- }