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 } }