PageRenderTime 51ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/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
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary;
  6. namespace Microsoft.Research.DynamicDataDisplay.Charts
  7. {
  8. internal abstract class TimePeriodTicksProvider<T> : ITicksProvider<T>
  9. {
  10. public event EventHandler Changed;
  11. protected void RaiseChanged()
  12. {
  13. if (Changed != null)
  14. {
  15. Changed(this, EventArgs.Empty);
  16. }
  17. }
  18. protected abstract T RoundUp(T time, DifferenceIn diff);
  19. protected abstract T RoundDown(T time, DifferenceIn diff);
  20. private bool differenceInited = false;
  21. private DifferenceIn difference;
  22. protected DifferenceIn Difference
  23. {
  24. get
  25. {
  26. if (!differenceInited)
  27. {
  28. difference = GetDifferenceCore();
  29. differenceInited = true;
  30. }
  31. return difference;
  32. }
  33. }
  34. protected abstract DifferenceIn GetDifferenceCore();
  35. private int[] tickCounts = null;
  36. protected int[] TickCounts
  37. {
  38. get
  39. {
  40. if (tickCounts == null)
  41. tickCounts = GetTickCountsCore();
  42. return tickCounts;
  43. }
  44. }
  45. protected abstract int[] GetTickCountsCore();
  46. public int DecreaseTickCount(int ticksCount)
  47. {
  48. if (ticksCount > TickCounts[0]) return TickCounts[0];
  49. for (int i = 0; i < TickCounts.Length; i++)
  50. if (ticksCount > TickCounts[i])
  51. return TickCounts[i];
  52. return TickCounts.Last();
  53. }
  54. public int IncreaseTickCount(int ticksCount)
  55. {
  56. if (ticksCount >= TickCounts[0]) return TickCounts[0];
  57. for (int i = TickCounts.Length - 1; i >= 0; i--)
  58. if (ticksCount < TickCounts[i])
  59. return TickCounts[i];
  60. return TickCounts.Last();
  61. }
  62. protected abstract int GetSpecificValue(T start, T dt);
  63. protected abstract T GetStart(T start, int value, int step);
  64. protected abstract bool IsMinDate(T dt);
  65. protected abstract T AddStep(T dt, int step);
  66. public ITicksInfo<T> GetTicks(Range<T> range, int ticksCount)
  67. {
  68. T start = range.Min;
  69. T end = range.Max;
  70. DifferenceIn diff = Difference;
  71. start = RoundDown(start, end);
  72. end = RoundUp(start, end);
  73. RoundingInfo bounds = RoundingHelper.CreateRoundedRange(
  74. GetSpecificValue(start, start),
  75. GetSpecificValue(start, end));
  76. int delta = (int)(bounds.Max - bounds.Min);
  77. if (delta == 0)
  78. return new TicksInfo<T> { Ticks = new T[] { start } };
  79. int step = delta / ticksCount;
  80. if (step == 0) step = 1;
  81. T tick = GetStart(start, (int)bounds.Min, step);
  82. bool isMinDateTime = IsMinDate(tick) && step != 1;
  83. if (isMinDateTime)
  84. step--;
  85. List<T> ticks = new List<T>();
  86. T finishTick = AddStep(range.Max, step);
  87. while (Continue(tick, finishTick))
  88. {
  89. ticks.Add(tick);
  90. tick = AddStep(tick, step);
  91. if (isMinDateTime)
  92. {
  93. isMinDateTime = false;
  94. step++;
  95. }
  96. }
  97. ticks = Trim(ticks, range);
  98. TicksInfo<T> res = new TicksInfo<T> { Ticks = ticks.ToArray(), Info = diff };
  99. return res;
  100. }
  101. protected abstract bool Continue(T current, T end);
  102. protected abstract T RoundUp(T start, T end);
  103. protected abstract T RoundDown(T start, T end);
  104. protected abstract List<T> Trim(List<T> ticks, Range<T> range);
  105. public ITicksProvider<T> MinorProvider
  106. {
  107. get { throw new NotSupportedException(); }
  108. }
  109. public ITicksProvider<T> MajorProvider
  110. {
  111. get { throw new NotSupportedException(); }
  112. }
  113. }
  114. internal abstract class DatePeriodTicksProvider : TimePeriodTicksProvider<DateTime>
  115. {
  116. protected sealed override bool Continue(DateTime current, DateTime end)
  117. {
  118. return current < end;
  119. }
  120. protected sealed override List<DateTime> Trim(List<DateTime> ticks, Range<DateTime> range)
  121. {
  122. int startIndex = 0;
  123. for (int i = 0; i < ticks.Count - 1; i++)
  124. {
  125. if (ticks[i] <= range.Min && range.Min <= ticks[i + 1])
  126. {
  127. startIndex = i;
  128. break;
  129. }
  130. }
  131. int endIndex = ticks.Count - 1;
  132. for (int i = ticks.Count - 1; i >= 1; i--)
  133. {
  134. if (ticks[i] >= range.Max && range.Max > ticks[i - 1])
  135. {
  136. endIndex = i;
  137. break;
  138. }
  139. }
  140. List<DateTime> res = new List<DateTime>(endIndex - startIndex + 1);
  141. for (int i = startIndex; i <= endIndex; i++)
  142. {
  143. res.Add(ticks[i]);
  144. }
  145. return res;
  146. }
  147. protected sealed override DateTime RoundUp(DateTime start, DateTime end)
  148. {
  149. bool isPositive = (end - start).Ticks > 0;
  150. return isPositive ? SafelyRoundUp(end) : RoundDown(end, Difference);
  151. }
  152. private DateTime SafelyRoundUp(DateTime dt)
  153. {
  154. if (AddStep(dt, 1) == DateTime.MaxValue)
  155. return DateTime.MaxValue;
  156. return RoundUp(dt, Difference);
  157. }
  158. protected sealed override DateTime RoundDown(DateTime start, DateTime end)
  159. {
  160. bool isPositive = (end - start).Ticks > 0;
  161. return isPositive ? RoundDown(start, Difference) : SafelyRoundUp(start);
  162. }
  163. protected sealed override DateTime RoundDown(DateTime time, DifferenceIn diff)
  164. {
  165. DateTime res = time;
  166. switch (diff)
  167. {
  168. case DifferenceIn.Year:
  169. res = new DateTime(time.Year, 1, 1);
  170. break;
  171. case DifferenceIn.Month:
  172. res = new DateTime(time.Year, time.Month, 1);
  173. break;
  174. case DifferenceIn.Day:
  175. res = time.Date;
  176. break;
  177. case DifferenceIn.Hour:
  178. res = time.Date.AddHours(time.Hour);
  179. break;
  180. case DifferenceIn.Minute:
  181. res = time.Date.AddHours(time.Hour).AddMinutes(time.Minute);
  182. break;
  183. case DifferenceIn.Second:
  184. res = time.Date.AddHours(time.Hour).AddMinutes(time.Minute).AddSeconds(time.Second);
  185. break;
  186. case DifferenceIn.Millisecond:
  187. res = time.Date.AddHours(time.Hour).AddMinutes(time.Minute).AddSeconds(time.Second).AddMilliseconds(time.Millisecond);
  188. break;
  189. default:
  190. break;
  191. }
  192. DebugVerify.Is(res <= time);
  193. return res;
  194. }
  195. protected override DateTime RoundUp(DateTime dateTime, DifferenceIn diff)
  196. {
  197. DateTime res = RoundDown(dateTime, diff);
  198. switch (diff)
  199. {
  200. case DifferenceIn.Year:
  201. res = res.AddYears(1);
  202. break;
  203. case DifferenceIn.Month:
  204. res = res.AddMonths(1);
  205. break;
  206. case DifferenceIn.Day:
  207. res = res.AddDays(1);
  208. break;
  209. case DifferenceIn.Hour:
  210. res = res.AddHours(1);
  211. break;
  212. case DifferenceIn.Minute:
  213. res = res.AddMinutes(1);
  214. break;
  215. case DifferenceIn.Second:
  216. res = res.AddSeconds(1);
  217. break;
  218. case DifferenceIn.Millisecond:
  219. res = res.AddMilliseconds(1);
  220. break;
  221. default:
  222. break;
  223. }
  224. return res;
  225. }
  226. }
  227. }