Initial Commit
This commit is contained in:
27
Charts/Axes/TimeSpan/HorizontalTimeSpanAxis.cs
Normal file
27
Charts/Axes/TimeSpan/HorizontalTimeSpanAxis.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Charts
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a horizontal axis with values of <see cref="TimeSpan"/> type.
|
||||
/// </summary>
|
||||
public class HorizontalTimeSpanAxis : TimeSpanAxis
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HorizontalTimeSpanAxis"/> class, placed on the bottom of <see cref="ChartPlotter"/>.
|
||||
/// </summary>
|
||||
public HorizontalTimeSpanAxis()
|
||||
{
|
||||
Placement = AxisPlacement.Bottom;
|
||||
}
|
||||
|
||||
protected override void ValidatePlacement(AxisPlacement newPlacement)
|
||||
{
|
||||
if (newPlacement == AxisPlacement.Left || newPlacement == AxisPlacement.Right)
|
||||
throw new ArgumentException(Strings.Exceptions.HorizontalAxisCannotBeVertical);
|
||||
}
|
||||
}
|
||||
}
|
||||
17
Charts/Axes/TimeSpan/MinorTimeSpanProvider.cs
Normal file
17
Charts/Axes/TimeSpan/MinorTimeSpanProvider.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Charts
|
||||
{
|
||||
internal sealed class MinorTimeSpanTicksProvider : MinorTimeProviderBase<TimeSpan>
|
||||
{
|
||||
public MinorTimeSpanTicksProvider(ITicksProvider<TimeSpan> owner) : base(owner) { }
|
||||
|
||||
protected override bool IsInside(TimeSpan value, Range<TimeSpan> range)
|
||||
{
|
||||
return range.Min < value && value < range.Max;
|
||||
}
|
||||
}
|
||||
}
|
||||
57
Charts/Axes/TimeSpan/TimeSpanAxis.cs
Normal file
57
Charts/Axes/TimeSpan/TimeSpanAxis.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Charts
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents axis with values of type TimeSpan.
|
||||
/// </summary>
|
||||
public class TimeSpanAxis : AxisBase<TimeSpan>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TimeSpanAxis"/> class with default values conversion.
|
||||
/// </summary>
|
||||
public TimeSpanAxis()
|
||||
: base(new TimeSpanAxisControl(),
|
||||
DoubleToTimeSpan, TimeSpanToDouble)
|
||||
{ }
|
||||
|
||||
private static readonly long minTicks = TimeSpan.MinValue.Ticks;
|
||||
private static readonly long maxTicks = TimeSpan.MaxValue.Ticks;
|
||||
private static TimeSpan DoubleToTimeSpan(double value)
|
||||
{
|
||||
long ticks = (long)(value * 10000000000L);
|
||||
|
||||
// todo should we throw an exception if number of ticks is too big or small?
|
||||
if (ticks < minTicks)
|
||||
ticks = minTicks;
|
||||
else if (ticks > maxTicks)
|
||||
ticks = maxTicks;
|
||||
|
||||
return new TimeSpan(ticks);
|
||||
}
|
||||
|
||||
private static double TimeSpanToDouble(TimeSpan time)
|
||||
{
|
||||
return time.Ticks / 10000000000.0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets conversions of axis - functions used to convert values of axis type to and from double values of viewport.
|
||||
/// Sets both ConvertToDouble and ConvertFromDouble properties.
|
||||
/// </summary>
|
||||
/// <param name="min">The minimal viewport value.</param>
|
||||
/// <param name="minValue">The value of axis type, corresponding to minimal viewport value.</param>
|
||||
/// <param name="max">The maximal viewport value.</param>
|
||||
/// <param name="maxValue">The value of axis type, corresponding to maximal viewport value.</param>
|
||||
public override void SetConversion(double min, TimeSpan minValue, double max, TimeSpan maxValue)
|
||||
{
|
||||
var conversion = new TimeSpanToDoubleConversion(min, minValue, max, maxValue);
|
||||
|
||||
ConvertToDouble = conversion.ToDouble;
|
||||
ConvertFromDouble = conversion.FromDouble;
|
||||
}
|
||||
}
|
||||
}
|
||||
20
Charts/Axes/TimeSpan/TimeSpanAxisControl.cs
Normal file
20
Charts/Axes/TimeSpan/TimeSpanAxisControl.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Charts
|
||||
{
|
||||
public class TimeSpanAxisControl : AxisControl<TimeSpan>
|
||||
{
|
||||
public TimeSpanAxisControl()
|
||||
{
|
||||
LabelProvider = new TimeSpanLabelProvider();
|
||||
TicksProvider = new TimeSpanTicksProvider();
|
||||
|
||||
ConvertToDouble = time => time.Ticks;
|
||||
|
||||
Range = new Range<TimeSpan>(new TimeSpan(), new TimeSpan(1, 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
33
Charts/Axes/TimeSpan/TimeSpanLabelProvider.cs
Normal file
33
Charts/Axes/TimeSpan/TimeSpanLabelProvider.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Microsoft.Research.DynamicDataDisplay.Charts.Axes;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Charts
|
||||
{
|
||||
public class TimeSpanLabelProvider : LabelProviderBase<TimeSpan>
|
||||
{
|
||||
public override UIElement[] CreateLabels(ITicksInfo<TimeSpan> ticksInfo)
|
||||
{
|
||||
object info = ticksInfo.Info;
|
||||
var ticks = ticksInfo.Ticks;
|
||||
|
||||
LabelTickInfo<TimeSpan> tickInfo = new LabelTickInfo<TimeSpan>();
|
||||
|
||||
UIElement[] res = new UIElement[ticks.Length];
|
||||
for (int i = 0; i < ticks.Length; i++)
|
||||
{
|
||||
tickInfo.Tick = ticks[i];
|
||||
tickInfo.Info = info;
|
||||
|
||||
string tickText = GetString(tickInfo);
|
||||
UIElement label = new TextBlock { Text = tickText, ToolTip = ticks[i] };
|
||||
res[i] = label;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Charts/Axes/TimeSpan/TimeSpanTicksProvider.cs
Normal file
34
Charts/Axes/TimeSpan/TimeSpanTicksProvider.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Charts
|
||||
{
|
||||
public class TimeSpanTicksProvider : TimeTicksProviderBase<TimeSpan>
|
||||
{
|
||||
static TimeSpanTicksProvider()
|
||||
{
|
||||
Providers.Add(DifferenceIn.Year, new DayTimeSpanProvider());
|
||||
Providers.Add(DifferenceIn.Month, new DayTimeSpanProvider());
|
||||
Providers.Add(DifferenceIn.Day, new DayTimeSpanProvider());
|
||||
Providers.Add(DifferenceIn.Hour, new HourTimeSpanProvider());
|
||||
Providers.Add(DifferenceIn.Minute, new MinuteTimeSpanProvider());
|
||||
Providers.Add(DifferenceIn.Second, new SecondTimeSpanProvider());
|
||||
Providers.Add(DifferenceIn.Millisecond, new MillisecondTimeSpanProvider());
|
||||
|
||||
MinorProviders.Add(DifferenceIn.Year, new MinorTimeSpanTicksProvider(new DayTimeSpanProvider()));
|
||||
MinorProviders.Add(DifferenceIn.Month, new MinorTimeSpanTicksProvider(new DayTimeSpanProvider()));
|
||||
MinorProviders.Add(DifferenceIn.Day, new MinorTimeSpanTicksProvider(new DayTimeSpanProvider()));
|
||||
MinorProviders.Add(DifferenceIn.Hour, new MinorTimeSpanTicksProvider(new HourTimeSpanProvider()));
|
||||
MinorProviders.Add(DifferenceIn.Minute, new MinorTimeSpanTicksProvider(new MinuteTimeSpanProvider()));
|
||||
MinorProviders.Add(DifferenceIn.Second, new MinorTimeSpanTicksProvider(new SecondTimeSpanProvider()));
|
||||
MinorProviders.Add(DifferenceIn.Millisecond, new MinorTimeSpanTicksProvider(new MillisecondTimeSpanProvider()));
|
||||
}
|
||||
|
||||
protected override TimeSpan GetDifference(TimeSpan start, TimeSpan end)
|
||||
{
|
||||
return end - start;
|
||||
}
|
||||
}
|
||||
}
|
||||
319
Charts/Axes/TimeSpan/TimeSpanTicksProviderBase.cs
Normal file
319
Charts/Axes/TimeSpan/TimeSpanTicksProviderBase.cs
Normal file
@@ -0,0 +1,319 @@
|
||||
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 TimeSpanTicksProviderBase : TimePeriodTicksProvider<TimeSpan>
|
||||
{
|
||||
protected sealed override bool Continue(TimeSpan current, TimeSpan end)
|
||||
{
|
||||
return current < end;
|
||||
}
|
||||
|
||||
protected sealed override TimeSpan RoundDown(TimeSpan start, TimeSpan end)
|
||||
{
|
||||
return RoundDown(start, Difference);
|
||||
}
|
||||
|
||||
protected sealed override TimeSpan RoundUp(TimeSpan start, TimeSpan end)
|
||||
{
|
||||
return RoundUp(end, Difference);
|
||||
}
|
||||
|
||||
protected static TimeSpan Shift(TimeSpan span, DifferenceIn diff)
|
||||
{
|
||||
TimeSpan res = span;
|
||||
|
||||
TimeSpan shift = new TimeSpan();
|
||||
switch (diff)
|
||||
{
|
||||
case DifferenceIn.Year:
|
||||
case DifferenceIn.Month:
|
||||
case DifferenceIn.Day:
|
||||
shift = TimeSpan.FromDays(1);
|
||||
break;
|
||||
case DifferenceIn.Hour:
|
||||
shift = TimeSpan.FromHours(1);
|
||||
break;
|
||||
case DifferenceIn.Minute:
|
||||
shift = TimeSpan.FromMinutes(1);
|
||||
break;
|
||||
case DifferenceIn.Second:
|
||||
shift = TimeSpan.FromSeconds(1);
|
||||
break;
|
||||
case DifferenceIn.Millisecond:
|
||||
shift = TimeSpan.FromMilliseconds(1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
res = res.Add(shift);
|
||||
return res;
|
||||
}
|
||||
|
||||
protected sealed override TimeSpan RoundDown(TimeSpan timeSpan, DifferenceIn diff)
|
||||
{
|
||||
TimeSpan res = timeSpan;
|
||||
|
||||
if (timeSpan.Ticks < 0)
|
||||
{
|
||||
res = RoundUp(timeSpan.Duration(), diff).Negate();
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (diff)
|
||||
{
|
||||
case DifferenceIn.Year:
|
||||
case DifferenceIn.Month:
|
||||
case DifferenceIn.Day:
|
||||
res = TimeSpan.FromDays(timeSpan.Days);
|
||||
break;
|
||||
case DifferenceIn.Hour:
|
||||
res = TimeSpan.FromDays(timeSpan.Days).
|
||||
Add(TimeSpan.FromHours(timeSpan.Hours));
|
||||
break;
|
||||
case DifferenceIn.Minute:
|
||||
res = TimeSpan.FromDays(timeSpan.Days).
|
||||
Add(TimeSpan.FromHours(timeSpan.Hours)).
|
||||
Add(TimeSpan.FromMinutes(timeSpan.Minutes));
|
||||
break;
|
||||
case DifferenceIn.Second:
|
||||
res = TimeSpan.FromDays(timeSpan.Days).
|
||||
Add(TimeSpan.FromHours(timeSpan.Hours)).
|
||||
Add(TimeSpan.FromMinutes(timeSpan.Minutes)).
|
||||
Add(TimeSpan.FromSeconds(timeSpan.Seconds));
|
||||
break;
|
||||
case DifferenceIn.Millisecond:
|
||||
res = timeSpan;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
protected sealed override TimeSpan RoundUp(TimeSpan dateTime, DifferenceIn diff)
|
||||
{
|
||||
TimeSpan res = RoundDown(dateTime, diff);
|
||||
res = Shift(res, diff);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
protected override List<TimeSpan> Trim(List<TimeSpan> ticks, Range<TimeSpan> 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<TimeSpan> res = new List<TimeSpan>(endIndex - startIndex + 1);
|
||||
for (int i = startIndex; i <= endIndex; i++)
|
||||
{
|
||||
res.Add(ticks[i]);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
protected sealed override bool IsMinDate(TimeSpan dt)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class DayTimeSpanProvider : TimeSpanTicksProviderBase
|
||||
{
|
||||
protected override DifferenceIn GetDifferenceCore()
|
||||
{
|
||||
return DifferenceIn.Day;
|
||||
}
|
||||
|
||||
protected override int[] GetTickCountsCore()
|
||||
{
|
||||
return new int[] { 20, 10, 5, 2, 1 };
|
||||
}
|
||||
|
||||
protected override int GetSpecificValue(TimeSpan start, TimeSpan dt)
|
||||
{
|
||||
return (dt - start).Days;
|
||||
}
|
||||
|
||||
protected override TimeSpan GetStart(TimeSpan start, int value, int step)
|
||||
{
|
||||
double days = start.TotalDays;
|
||||
double newDays = ((int)(days / step)) * step;
|
||||
if (newDays > days) {
|
||||
newDays -= step;
|
||||
}
|
||||
return TimeSpan.FromDays(newDays);
|
||||
//return TimeSpan.FromDays(start.Days);
|
||||
}
|
||||
|
||||
protected override TimeSpan AddStep(TimeSpan dt, int step)
|
||||
{
|
||||
return dt.Add(TimeSpan.FromDays(step));
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class HourTimeSpanProvider : TimeSpanTicksProviderBase
|
||||
{
|
||||
protected override DifferenceIn GetDifferenceCore()
|
||||
{
|
||||
return DifferenceIn.Hour;
|
||||
}
|
||||
|
||||
protected override int[] GetTickCountsCore()
|
||||
{
|
||||
return new int[] { 24, 12, 6, 4, 3, 2, 1 };
|
||||
}
|
||||
|
||||
protected override int GetSpecificValue(TimeSpan start, TimeSpan dt)
|
||||
{
|
||||
return (int)(dt - start).TotalHours;
|
||||
}
|
||||
|
||||
protected override TimeSpan GetStart(TimeSpan start, int value, int step)
|
||||
{
|
||||
double hours = start.TotalHours;
|
||||
double newHours = ((int)(hours / step)) * step;
|
||||
if (newHours > hours)
|
||||
{
|
||||
newHours -= step;
|
||||
}
|
||||
return TimeSpan.FromHours(newHours);
|
||||
//return TimeSpan.FromDays(start.Days);
|
||||
}
|
||||
|
||||
protected override TimeSpan AddStep(TimeSpan dt, int step)
|
||||
{
|
||||
return dt.Add(TimeSpan.FromHours(step));
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class MinuteTimeSpanProvider : TimeSpanTicksProviderBase
|
||||
{
|
||||
protected override DifferenceIn GetDifferenceCore()
|
||||
{
|
||||
return DifferenceIn.Minute;
|
||||
}
|
||||
|
||||
protected override int[] GetTickCountsCore()
|
||||
{
|
||||
return new int[] { 60, 30, 20, 15, 10, 5, 4, 3, 2 };
|
||||
}
|
||||
|
||||
protected override int GetSpecificValue(TimeSpan start, TimeSpan dt)
|
||||
{
|
||||
return (int)(dt - start).TotalMinutes;
|
||||
}
|
||||
|
||||
protected override TimeSpan GetStart(TimeSpan start, int value, int step)
|
||||
{
|
||||
double minutes = start.TotalMinutes;
|
||||
double newMinutes = ((int)(minutes / step)) * step;
|
||||
if (newMinutes > minutes)
|
||||
{
|
||||
newMinutes -= step;
|
||||
}
|
||||
|
||||
return TimeSpan.FromMinutes(newMinutes);
|
||||
}
|
||||
|
||||
protected override TimeSpan AddStep(TimeSpan dt, int step)
|
||||
{
|
||||
return dt.Add(TimeSpan.FromMinutes(step));
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class SecondTimeSpanProvider : TimeSpanTicksProviderBase
|
||||
{
|
||||
protected override DifferenceIn GetDifferenceCore()
|
||||
{
|
||||
return DifferenceIn.Second;
|
||||
}
|
||||
|
||||
protected override int[] GetTickCountsCore()
|
||||
{
|
||||
return new int[] { 60, 30, 20, 15, 10, 5, 4, 3, 2 };
|
||||
}
|
||||
|
||||
protected override int GetSpecificValue(TimeSpan start, TimeSpan dt)
|
||||
{
|
||||
return (int)(dt - start).TotalSeconds;
|
||||
}
|
||||
|
||||
protected override TimeSpan GetStart(TimeSpan start, int value, int step)
|
||||
{
|
||||
double seconds = start.TotalSeconds;
|
||||
double newSeconds = ((int)(seconds / step)) * step;
|
||||
if (newSeconds > seconds) {
|
||||
newSeconds -= step;
|
||||
}
|
||||
|
||||
return TimeSpan.FromSeconds(newSeconds);
|
||||
//return new TimeSpan(start.Days, start.Hours, start.Minutes, 0);
|
||||
}
|
||||
|
||||
protected override TimeSpan AddStep(TimeSpan dt, int step)
|
||||
{
|
||||
return dt.Add(TimeSpan.FromSeconds(step));
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class MillisecondTimeSpanProvider : TimeSpanTicksProviderBase
|
||||
{
|
||||
protected override DifferenceIn GetDifferenceCore()
|
||||
{
|
||||
return DifferenceIn.Millisecond;
|
||||
}
|
||||
|
||||
protected override int[] GetTickCountsCore()
|
||||
{
|
||||
return new int[] { 100, 50, 40, 25, 20, 10, 5, 4, 2 };
|
||||
}
|
||||
|
||||
protected override int GetSpecificValue(TimeSpan start, TimeSpan dt)
|
||||
{
|
||||
return (int)(dt - start).TotalMilliseconds;
|
||||
}
|
||||
|
||||
protected override TimeSpan GetStart(TimeSpan start, int value, int step)
|
||||
{
|
||||
double millis = start.TotalMilliseconds;
|
||||
double newMillis = ((int)(millis / step)) * step;
|
||||
if (newMillis > millis) {
|
||||
newMillis -= step;
|
||||
}
|
||||
|
||||
return TimeSpan.FromMilliseconds(newMillis);
|
||||
//return start;
|
||||
}
|
||||
|
||||
protected override TimeSpan AddStep(TimeSpan dt, int step)
|
||||
{
|
||||
return dt.Add(TimeSpan.FromMilliseconds(step));
|
||||
}
|
||||
}
|
||||
}
|
||||
44
Charts/Axes/TimeSpan/TimeSpanToDoubleConversion.cs
Normal file
44
Charts/Axes/TimeSpan/TimeSpanToDoubleConversion.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Charts
|
||||
{
|
||||
internal sealed class TimeSpanToDoubleConversion
|
||||
{
|
||||
public TimeSpanToDoubleConversion(TimeSpan minSpan, TimeSpan maxSpan)
|
||||
: this(0, minSpan, 1, maxSpan)
|
||||
{ }
|
||||
|
||||
public TimeSpanToDoubleConversion(double min, TimeSpan minSpan, double max, TimeSpan maxSpan)
|
||||
{
|
||||
this.min = min;
|
||||
this.length = max - min;
|
||||
this.ticksMin = minSpan.Ticks;
|
||||
this.ticksLength = maxSpan.Ticks - ticksMin;
|
||||
}
|
||||
|
||||
private double min;
|
||||
private double length;
|
||||
private long ticksMin;
|
||||
private long ticksLength;
|
||||
|
||||
internal TimeSpan FromDouble(double d)
|
||||
{
|
||||
double ratio = (d - min) / length;
|
||||
long ticks = (long)(ticksMin + ticksLength * ratio);
|
||||
|
||||
ticks = MathHelper.Clamp(ticks, TimeSpan.MinValue.Ticks, TimeSpan.MaxValue.Ticks);
|
||||
|
||||
return new TimeSpan(ticks);
|
||||
}
|
||||
|
||||
internal double ToDouble(TimeSpan span)
|
||||
{
|
||||
double ratio = (span.Ticks - ticksMin) / (double)ticksLength;
|
||||
return min + ratio * length;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
159
Charts/Axes/TimeSpan/TimeTicksProviderBase.cs
Normal file
159
Charts/Axes/TimeSpan/TimeTicksProviderBase.cs
Normal file
@@ -0,0 +1,159 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Charts
|
||||
{
|
||||
public abstract class TimeTicksProviderBase<T> : ITicksProvider<T>
|
||||
{
|
||||
public event EventHandler Changed;
|
||||
protected void RaiseChanged()
|
||||
{
|
||||
if (Changed != null)
|
||||
{
|
||||
Changed(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Dictionary<DifferenceIn, ITicksProvider<T>> providers =
|
||||
new Dictionary<DifferenceIn, ITicksProvider<T>>();
|
||||
|
||||
protected static Dictionary<DifferenceIn, ITicksProvider<T>> Providers
|
||||
{
|
||||
get { return TimeTicksProviderBase<T>.providers; }
|
||||
}
|
||||
|
||||
private static readonly Dictionary<DifferenceIn, ITicksProvider<T>> minorProviders =
|
||||
new Dictionary<DifferenceIn, ITicksProvider<T>>();
|
||||
|
||||
protected static Dictionary<DifferenceIn, ITicksProvider<T>> MinorProviders
|
||||
{
|
||||
get { return TimeTicksProviderBase<T>.minorProviders; }
|
||||
}
|
||||
|
||||
protected abstract TimeSpan GetDifference(T start, T end);
|
||||
|
||||
#region ITicksProvider<T> Members
|
||||
|
||||
private IDateTimeTicksStrategy strategy = new DefaultDateTimeTicksStrategy();
|
||||
public IDateTimeTicksStrategy Strategy
|
||||
{
|
||||
get { return strategy; }
|
||||
set
|
||||
{
|
||||
if (strategy != value)
|
||||
{
|
||||
strategy = value;
|
||||
RaiseChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ITicksInfo<T> result;
|
||||
private DifferenceIn diff;
|
||||
|
||||
public ITicksInfo<T> GetTicks(Range<T> range, int ticksCount)
|
||||
{
|
||||
Verify.IsTrue(ticksCount > 0);
|
||||
|
||||
T start = range.Min;
|
||||
T end = range.Max;
|
||||
TimeSpan length = GetDifference(start, end);
|
||||
|
||||
diff = strategy.GetDifference(length);
|
||||
|
||||
TicksInfo<T> result = new TicksInfo<T> { Info = diff };
|
||||
if (providers.ContainsKey(diff))
|
||||
{
|
||||
ITicksInfo<T> innerResult = providers[diff].GetTicks(range, ticksCount);
|
||||
T[] ticks = ModifyTicksGuard(innerResult.Ticks, diff);
|
||||
|
||||
result.Ticks = ticks;
|
||||
this.result = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException(Strings.Exceptions.UnsupportedRangeInAxis);
|
||||
}
|
||||
|
||||
private T[] ModifyTicksGuard(T[] ticks, object info)
|
||||
{
|
||||
var result = ModifyTicks(ticks, info);
|
||||
if (result == null)
|
||||
throw new ArgumentNullException("ticks");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected virtual T[] ModifyTicks(T[] ticks, object info)
|
||||
{
|
||||
return ticks;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decreases the tick count.
|
||||
/// </summary>
|
||||
/// <param name="tickCount">The tick count.</param>
|
||||
/// <returns></returns>
|
||||
public int DecreaseTickCount(int ticksCount)
|
||||
{
|
||||
if (providers.ContainsKey(diff))
|
||||
return providers[diff].DecreaseTickCount(ticksCount);
|
||||
|
||||
int res = ticksCount / 2;
|
||||
if (res < 2) res = 2;
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increases the tick count.
|
||||
/// </summary>
|
||||
/// <param name="ticksCount">The tick count.</param>
|
||||
/// <returns></returns>
|
||||
public int IncreaseTickCount(int ticksCount)
|
||||
{
|
||||
DebugVerify.Is(ticksCount < 2000);
|
||||
|
||||
if (providers.ContainsKey(diff))
|
||||
return providers[diff].IncreaseTickCount(ticksCount);
|
||||
|
||||
return ticksCount * 2;
|
||||
}
|
||||
|
||||
public ITicksProvider<T> MinorProvider
|
||||
{
|
||||
get
|
||||
{
|
||||
DifferenceIn smallerDiff = DifferenceIn.Smallest;
|
||||
if (strategy.TryGetLowerDiff(diff, out smallerDiff) && minorProviders.ContainsKey(smallerDiff))
|
||||
{
|
||||
var minorProvider = (MinorTimeProviderBase<T>)minorProviders[smallerDiff];
|
||||
minorProvider.SetTicks(result.Ticks);
|
||||
return minorProvider;
|
||||
}
|
||||
|
||||
return null;
|
||||
// todo What to do if this already is the smallest provider?
|
||||
}
|
||||
}
|
||||
|
||||
public ITicksProvider<T> MajorProvider
|
||||
{
|
||||
get
|
||||
{
|
||||
DifferenceIn biggerDiff = DifferenceIn.Smallest;
|
||||
if (strategy.TryGetBiggerDiff(diff, out biggerDiff))
|
||||
{
|
||||
return providers[biggerDiff];
|
||||
}
|
||||
|
||||
return null;
|
||||
// todo What to do if this already is the biggest provider?
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
32
Charts/Axes/TimeSpan/VerticalTimeSpanAxis.cs
Normal file
32
Charts/Axes/TimeSpan/VerticalTimeSpanAxis.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Charts
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a vertical axis with values of <see cref="TimeSpan"/> type.
|
||||
/// </summary>
|
||||
public class VerticalTimeSpanAxis : TimeSpanAxis
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="VerticalTimeSpanAxis"/> class, placed (by default) on the left side of <see cref="ChartPlotter"/>.
|
||||
/// </summary>
|
||||
public VerticalTimeSpanAxis()
|
||||
{
|
||||
Placement = AxisPlacement.Left;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the placement - e.g., vertical axis should not be placed from top or bottom, etc.
|
||||
/// If proposed placement is wrong, throws an ArgumentException.
|
||||
/// </summary>
|
||||
/// <param name="newPlacement">The new placement.</param>
|
||||
protected override void ValidatePlacement(AxisPlacement newPlacement)
|
||||
{
|
||||
if (newPlacement == AxisPlacement.Bottom || newPlacement == AxisPlacement.Top)
|
||||
throw new ArgumentException(Strings.Exceptions.VerticalAxisCannotBeHorizontal);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user