Initial Commit
This commit is contained in:
269
Charts/Axes/DateTime/TimePeriodTicksProvider.cs
Normal file
269
Charts/Axes/DateTime/TimePeriodTicksProvider.cs
Normal file
@@ -0,0 +1,269 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user