using System.Windows;
using System.Windows.Media;
using Microsoft.Research.DynamicDataDisplay.Charts;
using System.Windows.Controls;
using System;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using Microsoft.Research.DynamicDataDisplay.Common;
using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary;
namespace Microsoft.Research.DynamicDataDisplay
{
///
/// Draws grid over viewport. Number of
/// grid lines depends on Plotter's MainHorizontalAxis and MainVerticalAxis ticks.
///
public class AxisGrid : ContentControl, IPlotterElement
{
static AxisGrid()
{
Type thisType = typeof(AxisGrid);
Panel.ZIndexProperty.OverrideMetadata(thisType, new FrameworkPropertyMetadata(-1));
}
[SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
internal void BeginTicksUpdate()
{
}
internal void EndTicksUpdate()
{
UpdateUIRepresentation();
}
protected internal MinorTickInfo[] MinorHorizontalTicks { get; set; }
protected internal MinorTickInfo[] MinorVerticalTicks { get; set; }
protected internal double[] HorizontalTicks { get; set; }
protected internal double[] VerticalTicks { get; set; }
private bool drawVerticalTicks = true;
///
/// Gets or sets a value indicating whether to draw vertical tick lines.
///
/// true if draw vertical ticks; otherwise, false.
public bool DrawVerticalTicks
{
get { return drawVerticalTicks; }
set
{
if (drawVerticalTicks != value)
{
drawVerticalTicks = value;
UpdateUIRepresentation();
}
}
}
private bool drawHorizontalTicks = true;
///
/// Gets or sets a value indicating whether to draw horizontal tick lines.
///
/// true if draw horizontal ticks; otherwise, false.
public bool DrawHorizontalTicks
{
get { return drawHorizontalTicks; }
set
{
if (drawHorizontalTicks != value)
{
drawHorizontalTicks = value;
UpdateUIRepresentation();
}
}
}
private bool drawHorizontalMinorTicks = false;
///
/// Gets or sets a value indicating whether to draw horizontal minor ticks.
///
///
/// true if draw horizontal minor ticks; otherwise, false.
///
public bool DrawHorizontalMinorTicks
{
get { return drawHorizontalMinorTicks; }
set
{
if (drawHorizontalMinorTicks != value)
{
drawHorizontalMinorTicks = value;
UpdateUIRepresentation();
}
}
}
private bool drawVerticalMinorTicks = false;
///
/// Gets or sets a value indicating whether to draw vertical minor ticks.
///
///
/// true if draw vertical minor ticks; otherwise, false.
///
public bool DrawVerticalMinorTicks
{
get { return drawVerticalMinorTicks; }
set
{
if (drawVerticalMinorTicks != value)
{
drawVerticalMinorTicks = value;
UpdateUIRepresentation();
}
}
}
private double gridBrushThickness = 1;
private Path path = new Path();
private Canvas canvas = new Canvas();
///
/// Initializes a new instance of the class.
///
public AxisGrid()
{
IsHitTestVisible = false;
canvas.ClipToBounds = true;
path.Stroke = Brushes.LightGray;
path.StrokeThickness = gridBrushThickness;
Content = canvas;
}
private readonly ResourcePool lineGeometryPool = new ResourcePool();
private readonly ResourcePool linePool = new ResourcePool();
private void UpdateUIRepresentation()
{
foreach (UIElement item in canvas.Children)
{
Line line = item as Line;
if (line != null)
{
linePool.Put(line);
}
}
canvas.Children.Clear();
Size size = RenderSize;
DrawMinorHorizontalTicks();
DrawMinorVerticalTicks();
GeometryGroup prevGroup = path.Data as GeometryGroup;
if (prevGroup != null)
{
foreach (LineGeometry geometry in prevGroup.Children)
{
lineGeometryPool.Put(geometry);
}
}
GeometryGroup group = new GeometryGroup();
if (HorizontalTicks != null && drawHorizontalTicks)
{
double minY = 0;
double maxY = size.Height;
for (int i = 0; i < HorizontalTicks.Length; i++)
{
double screenX = HorizontalTicks[i];
LineGeometry line = lineGeometryPool.GetOrCreate();
line.StartPoint = new Point(screenX, minY);
line.EndPoint = new Point(screenX, maxY);
group.Children.Add(line);
}
}
if (VerticalTicks != null && drawVerticalTicks)
{
double minX = 0;
double maxX = size.Width;
for (int i = 0; i < VerticalTicks.Length; i++)
{
double screenY = VerticalTicks[i];
LineGeometry line = lineGeometryPool.GetOrCreate();
line.StartPoint = new Point(minX, screenY);
line.EndPoint = new Point(maxX, screenY);
group.Children.Add(line);
}
}
canvas.Children.Add(path);
path.Data = group;
}
private void DrawMinorVerticalTicks()
{
Size size = RenderSize;
if (MinorVerticalTicks != null && drawVerticalMinorTicks)
{
double minX = 0;
double maxX = size.Width;
for (int i = 0; i < MinorVerticalTicks.Length; i++)
{
double screenY = MinorVerticalTicks[i].Tick;
if (screenY < 0)
continue;
if (screenY > size.Height)
continue;
Line line = linePool.GetOrCreate();
line.Y1 = screenY;
line.Y2 = screenY;
line.X1 = minX;
line.X2 = maxX;
line.Stroke = Brushes.LightGray;
line.StrokeThickness = MinorVerticalTicks[i].Value * gridBrushThickness;
canvas.Children.Add(line);
}
}
}
private void DrawMinorHorizontalTicks()
{
Size size = RenderSize;
if (MinorHorizontalTicks != null && drawHorizontalMinorTicks)
{
double minY = 0;
double maxY = size.Height;
for (int i = 0; i < MinorHorizontalTicks.Length; i++)
{
double screenX = MinorHorizontalTicks[i].Tick;
if (screenX < 0)
continue;
if (screenX > size.Width)
continue;
Line line = linePool.GetOrCreate();
line.X1 = screenX;
line.X2 = screenX;
line.Y1 = minY;
line.Y2 = maxY;
line.Stroke = Brushes.LightGray;
line.StrokeThickness = MinorHorizontalTicks[i].Value * gridBrushThickness;
canvas.Children.Add(line);
}
}
}
#region IPlotterElement Members
void IPlotterElement.OnPlotterAttached(Plotter plotter)
{
this.plotter = plotter;
plotter.CentralGrid.Children.Add(this);
}
void IPlotterElement.OnPlotterDetaching(Plotter plotter)
{
plotter.CentralGrid.Children.Remove(this);
this.plotter = null;
}
private Plotter plotter;
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Plotter Plotter
{
get { return plotter; }
}
#endregion
}
}