Initial Commit
This commit is contained in:
107
Charts/Axes/Integer/CollectionLabelProvider.cs
Normal file
107
Charts/Axes/Integer/CollectionLabelProvider.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Charts.Axes
|
||||
{
|
||||
public class CollectionLabelProvider<T> : LabelProviderBase<int>
|
||||
{
|
||||
private IList<T> collection;
|
||||
|
||||
[SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
|
||||
public IList<T> Collection
|
||||
{
|
||||
get { return collection; }
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
if (collection != value)
|
||||
{
|
||||
DetachCollection();
|
||||
|
||||
collection = value;
|
||||
|
||||
AttachCollection();
|
||||
|
||||
RaiseChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Collection changed
|
||||
|
||||
private void AttachCollection()
|
||||
{
|
||||
INotifyCollectionChanged observableCollection = collection as INotifyCollectionChanged;
|
||||
if (observableCollection != null)
|
||||
{
|
||||
observableCollection.CollectionChanged += OnCollectionChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
RaiseChanged();
|
||||
}
|
||||
|
||||
private void DetachCollection()
|
||||
{
|
||||
INotifyCollectionChanged observableCollection = collection as INotifyCollectionChanged;
|
||||
if (observableCollection != null)
|
||||
{
|
||||
observableCollection.CollectionChanged -= OnCollectionChanged;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CollectionLabelProvider<T>"/> class with empty labels collection.
|
||||
/// </summary>
|
||||
public CollectionLabelProvider() { }
|
||||
|
||||
public CollectionLabelProvider(IList<T> collection)
|
||||
: this()
|
||||
{
|
||||
Collection = collection;
|
||||
}
|
||||
|
||||
public override UIElement[] CreateLabels(ITicksInfo<int> ticksInfo)
|
||||
{
|
||||
var ticks = ticksInfo.Ticks;
|
||||
|
||||
UIElement[] res = new UIElement[ticks.Length];
|
||||
|
||||
var tickInfo = new LabelTickInfo<int> { Info = ticksInfo.Info };
|
||||
|
||||
for (int i = 0; i < res.Length; i++)
|
||||
{
|
||||
int tick = ticks[i];
|
||||
tickInfo.Tick = tick;
|
||||
|
||||
if (0 <= tick && tick < collection.Count)
|
||||
{
|
||||
string text = collection[tick].ToString();
|
||||
res[i] = new TextBlock
|
||||
{
|
||||
Text = text,
|
||||
ToolTip = text
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
res[i] = null;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
21
Charts/Axes/Integer/HorizontalIntegerAxis.cs
Normal file
21
Charts/Axes/Integer/HorizontalIntegerAxis.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Charts.Axes
|
||||
{
|
||||
public class HorizontalIntegerAxis : IntegerAxis
|
||||
{
|
||||
public HorizontalIntegerAxis()
|
||||
{
|
||||
Placement = AxisPlacement.Bottom;
|
||||
}
|
||||
|
||||
protected override void ValidatePlacement(AxisPlacement newPlacement)
|
||||
{
|
||||
if (newPlacement == AxisPlacement.Left || newPlacement == AxisPlacement.Right)
|
||||
throw new ArgumentException(Strings.Exceptions.HorizontalAxisCannotBeVertical);
|
||||
}
|
||||
}
|
||||
}
|
||||
18
Charts/Axes/Integer/IntegerAxis.cs
Normal file
18
Charts/Axes/Integer/IntegerAxis.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Charts.Axes
|
||||
{
|
||||
public class IntegerAxis : AxisBase<int>
|
||||
{
|
||||
public IntegerAxis()
|
||||
: base(new IntegerAxisControl(),
|
||||
d => (int)d,
|
||||
i => (double)i)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
18
Charts/Axes/Integer/IntegerAxisControl.cs
Normal file
18
Charts/Axes/Integer/IntegerAxisControl.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Charts.Axes
|
||||
{
|
||||
public class IntegerAxisControl : AxisControl<int>
|
||||
{
|
||||
public IntegerAxisControl()
|
||||
{
|
||||
LabelProvider = new GenericLabelProvider<int>();
|
||||
TicksProvider = new IntegerTicksProvider();
|
||||
ConvertToDouble = i => (double)i;
|
||||
Range = new Range<int>(0, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
189
Charts/Axes/Integer/IntegerTicksProvider.cs
Normal file
189
Charts/Axes/Integer/IntegerTicksProvider.cs
Normal file
@@ -0,0 +1,189 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Charts.Axes
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a ticks provider for intefer values.
|
||||
/// </summary>
|
||||
public class IntegerTicksProvider : ITicksProvider<int>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="IntegerTicksProvider"/> class.
|
||||
/// </summary>
|
||||
public IntegerTicksProvider() { }
|
||||
|
||||
private int minStep = 0;
|
||||
/// <summary>
|
||||
/// Gets or sets the minimal step between ticks.
|
||||
/// </summary>
|
||||
/// <value>The min step.</value>
|
||||
public int MinStep
|
||||
{
|
||||
get { return minStep; }
|
||||
set
|
||||
{
|
||||
Verify.IsTrue(value >= 0, "value");
|
||||
if (minStep != value)
|
||||
{
|
||||
minStep = value;
|
||||
RaiseChangedEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int maxStep = Int32.MaxValue;
|
||||
/// <summary>
|
||||
/// Gets or sets the maximal step between ticks.
|
||||
/// </summary>
|
||||
/// <value>The max step.</value>
|
||||
public int MaxStep
|
||||
{
|
||||
get { return maxStep; }
|
||||
set
|
||||
{
|
||||
if (maxStep != value)
|
||||
{
|
||||
if (value < 0)
|
||||
throw new ArgumentOutOfRangeException("value", Strings.Exceptions.ParameterShouldBePositive);
|
||||
|
||||
maxStep = value;
|
||||
RaiseChangedEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region ITicksProvider<int> Members
|
||||
|
||||
/// <summary>
|
||||
/// Generates ticks for given range and preferred ticks count.
|
||||
/// </summary>
|
||||
/// <param name="range">The range.</param>
|
||||
/// <param name="ticksCount">The ticks count.</param>
|
||||
/// <returns></returns>
|
||||
public ITicksInfo<int> GetTicks(Range<int> range, int ticksCount)
|
||||
{
|
||||
double start = range.Min;
|
||||
double finish = range.Max;
|
||||
|
||||
double delta = finish - start;
|
||||
|
||||
int log = (int)Math.Round(Math.Log10(delta));
|
||||
|
||||
double newStart = RoundingHelper.Round(start, log);
|
||||
double newFinish = RoundingHelper.Round(finish, log);
|
||||
if (newStart == newFinish)
|
||||
{
|
||||
log--;
|
||||
newStart = RoundingHelper.Round(start, log);
|
||||
newFinish = RoundingHelper.Round(finish, log);
|
||||
}
|
||||
|
||||
// calculating step between ticks
|
||||
double unroundedStep = (newFinish - newStart) / ticksCount;
|
||||
int stepLog = log;
|
||||
// trying to round step
|
||||
int step = (int)RoundingHelper.Round(unroundedStep, stepLog);
|
||||
if (step == 0)
|
||||
{
|
||||
stepLog--;
|
||||
step = (int)RoundingHelper.Round(unroundedStep, stepLog);
|
||||
if (step == 0)
|
||||
{
|
||||
// step will not be rounded if attempts to be rounded to zero.
|
||||
step = (int)unroundedStep;
|
||||
}
|
||||
}
|
||||
|
||||
if (step < minStep)
|
||||
step = minStep;
|
||||
if (step > maxStep)
|
||||
step = maxStep;
|
||||
|
||||
if (step <= 0)
|
||||
step = 1;
|
||||
|
||||
int[] ticks = CreateTicks(start, finish, step);
|
||||
|
||||
TicksInfo<int> res = new TicksInfo<int> { Info = log, Ticks = ticks };
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private static int[] CreateTicks(double start, double finish, int step)
|
||||
{
|
||||
DebugVerify.Is(step != 0);
|
||||
|
||||
int x = (int)(step * Math.Floor(start / (double)step));
|
||||
List<int> res = new List<int>();
|
||||
|
||||
checked
|
||||
{
|
||||
double increasedFinish = finish + step * 1.05;
|
||||
while (x <= increasedFinish)
|
||||
{
|
||||
res.Add(x);
|
||||
x += step;
|
||||
}
|
||||
}
|
||||
return res.ToArray();
|
||||
}
|
||||
|
||||
private static int[] tickCounts = new int[] { 20, 10, 5, 4, 2, 1 };
|
||||
|
||||
/// <summary>
|
||||
/// Decreases the tick count.
|
||||
/// Returned value should be later passed as ticksCount parameter to GetTicks method.
|
||||
/// </summary>
|
||||
/// <param name="ticksCount">The ticks count.</param>
|
||||
/// <returns>Decreased ticks count.</returns>
|
||||
public int DecreaseTickCount(int ticksCount)
|
||||
{
|
||||
return tickCounts.FirstOrDefault(tick => tick < ticksCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increases the tick count.
|
||||
/// Returned value should be later passed as ticksCount parameter to GetTicks method.
|
||||
/// </summary>
|
||||
/// <param name="ticksCount">The ticks count.</param>
|
||||
/// <returns>Increased ticks count.</returns>
|
||||
public int IncreaseTickCount(int ticksCount)
|
||||
{
|
||||
int newTickCount = tickCounts.Reverse().FirstOrDefault(tick => tick > ticksCount);
|
||||
if (newTickCount == 0)
|
||||
newTickCount = tickCounts[0];
|
||||
|
||||
return newTickCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the minor ticks provider, used to generate ticks between each two adjacent ticks.
|
||||
/// </summary>
|
||||
/// <value>The minor provider.</value>
|
||||
public ITicksProvider<int> MinorProvider
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the major provider, used to generate major ticks - for example, years for common ticks as months.
|
||||
/// </summary>
|
||||
/// <value>The major provider.</value>
|
||||
public ITicksProvider<int> MajorProvider
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
protected void RaiseChangedEvent()
|
||||
{
|
||||
Changed.Raise(this);
|
||||
}
|
||||
public event EventHandler Changed;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
21
Charts/Axes/Integer/VerticalIntegerAxis.cs
Normal file
21
Charts/Axes/Integer/VerticalIntegerAxis.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Charts.Axes
|
||||
{
|
||||
public class VerticalIntegerAxis : IntegerAxis
|
||||
{
|
||||
public VerticalIntegerAxis()
|
||||
{
|
||||
Placement = AxisPlacement.Left;
|
||||
}
|
||||
|
||||
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