Initial Commit
This commit is contained in:
84
PointMarkers/CenteredTextMarker.cs
Normal file
84
PointMarkers/CenteredTextMarker.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.PointMarkers
|
||||
{
|
||||
/// <summary>Renders specified text near the point</summary>
|
||||
public class CenteredTextMarker : PointMarker
|
||||
{
|
||||
public static double DEFAULT_VERTICAL_SHIFT=-20;
|
||||
public static double DEFAULT_HORIZONTAL_SHIFT=0;
|
||||
public string Text
|
||||
{
|
||||
get { return (string)GetValue(TextProperty); }
|
||||
set { SetValue(TextProperty, value); }
|
||||
}
|
||||
public static readonly DependencyProperty TextProperty =
|
||||
DependencyProperty.Register(
|
||||
"Text",
|
||||
typeof(string),
|
||||
typeof(CenteredTextMarker),
|
||||
new FrameworkPropertyMetadata(""));
|
||||
|
||||
|
||||
public static readonly DependencyProperty VerticalShiftProperty =
|
||||
DependencyProperty.Register(
|
||||
"VerticalShift",
|
||||
typeof(string),
|
||||
typeof(CenteredTextMarker),
|
||||
new FrameworkPropertyMetadata(""));
|
||||
|
||||
public static readonly DependencyProperty HorizontalShiftProperty =
|
||||
DependencyProperty.Register(
|
||||
"HorizontalShift",
|
||||
typeof(string),
|
||||
typeof(CenteredTextMarker),
|
||||
new FrameworkPropertyMetadata(""));
|
||||
|
||||
public string VerticalShift
|
||||
{
|
||||
get { return (string)GetValue(VerticalShiftProperty); }
|
||||
set { SetValue(VerticalShiftProperty, value); }
|
||||
}
|
||||
|
||||
public string HorizontalShift
|
||||
{
|
||||
get { return (string)GetValue(HorizontalShiftProperty); }
|
||||
set { SetValue(HorizontalShiftProperty, value); }
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext dc, Point screenPoint)
|
||||
{
|
||||
FormattedText textToDraw = new FormattedText(Text, Thread.CurrentThread.CurrentCulture,
|
||||
FlowDirection.LeftToRight, new Typeface("Arial"), 12, Brushes.Black,1.0);
|
||||
|
||||
double width = textToDraw.Width;
|
||||
double height = textToDraw.Height;
|
||||
|
||||
double verticalShift = DEFAULT_VERTICAL_SHIFT; // px
|
||||
if (null != VerticalShift&&!"".Equals(VerticalShift))verticalShift = double.Parse(VerticalShift);
|
||||
|
||||
double horizontalShift=DEFAULT_HORIZONTAL_SHIFT;
|
||||
if (null != HorizontalShift&&!"".Equals(HorizontalShift)) horizontalShift = double.Parse(HorizontalShift);
|
||||
|
||||
// Rect bounds = RectExtensions.FromCenterSize(new Point(screenPoint.X+horizontalShift, screenPoint.Y + verticalShift - height / 2),new Size(width, height));
|
||||
double xPoint=0.00;
|
||||
double yPoint=0.00;
|
||||
if(0.00==horizontalShift)xPoint=screenPoint.X+horizontalShift;
|
||||
else xPoint=screenPoint.X+horizontalShift - width/2;
|
||||
yPoint=screenPoint.Y + verticalShift - height / 2;
|
||||
Rect bounds = RectExtensions.FromCenterSize(new Point(xPoint, yPoint),new Size(width, height));
|
||||
|
||||
// forcing the X bound is incorrect as this will always force the text into the visible viewport even when it should be out of view
|
||||
// if(bounds.X<0)bounds.X=Math.Abs(horizontalShift);
|
||||
Point loc = bounds.Location;
|
||||
bounds = CoordinateUtilities.RectZoom(bounds, 1.05, 1.15);
|
||||
|
||||
dc.DrawLine(new Pen(Brushes.Black, 1), Point.Add(screenPoint, new Vector(0, verticalShift)), screenPoint);
|
||||
dc.DrawRectangle(Brushes.White, new Pen(Brushes.Black, 1), bounds);
|
||||
dc.DrawText(textToDraw, loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
50
PointMarkers/CircleElementPointMarker.cs
Normal file
50
PointMarkers/CircleElementPointMarker.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.PointMarkers
|
||||
{
|
||||
/// <summary>Adds Circle element at every point of graph</summary>
|
||||
public class CircleElementPointMarker : ShapeElementPointMarker {
|
||||
|
||||
public override UIElement CreateMarker()
|
||||
{
|
||||
Ellipse result = new Ellipse();
|
||||
result.Width = Size;
|
||||
result.Height = Size;
|
||||
result.Stroke = Brush;
|
||||
result.Fill = Fill;
|
||||
if (!String.IsNullOrEmpty(ToolTipText))
|
||||
{
|
||||
ToolTip tt = new ToolTip();
|
||||
tt.Content = ToolTipText;
|
||||
result.ToolTip = tt;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public override void SetMarkerProperties(UIElement marker)
|
||||
{
|
||||
Ellipse ellipse = (Ellipse)marker;
|
||||
|
||||
ellipse.Width = Size;
|
||||
ellipse.Height = Size;
|
||||
ellipse.Stroke = Brush;
|
||||
ellipse.Fill = Fill;
|
||||
|
||||
if (!String.IsNullOrEmpty(ToolTipText))
|
||||
{
|
||||
ToolTip tt = new ToolTip();
|
||||
tt.Content = ToolTipText;
|
||||
ellipse.ToolTip = tt;
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetPosition(UIElement marker, Point screenPoint)
|
||||
{
|
||||
Canvas.SetLeft(marker, screenPoint.X - Size / 2);
|
||||
Canvas.SetTop(marker, screenPoint.Y - Size / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
14
PointMarkers/CirclePointMarker.cs
Normal file
14
PointMarkers/CirclePointMarker.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.PointMarkers
|
||||
{
|
||||
/// <summary>Renders circle around each point of graph</summary>
|
||||
public class CirclePointMarker : ShapePointMarker {
|
||||
|
||||
public override void Render(DrawingContext dc, Point screenPoint) {
|
||||
dc.DrawEllipse(Fill, Pen, screenPoint, Size / 2, Size / 2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
49
PointMarkers/CompositePointMarker.cs
Normal file
49
PointMarkers/CompositePointMarker.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.PointMarkers
|
||||
{
|
||||
/// <summary>Composite point markers renders a specified set of markers
|
||||
/// at every point of graph</summary>
|
||||
public sealed class CompositePointMarker : PointMarker {
|
||||
public CompositePointMarker() { }
|
||||
|
||||
public CompositePointMarker(params PointMarker[] markers) {
|
||||
if (markers == null)
|
||||
throw new ArgumentNullException("markers");
|
||||
|
||||
foreach (PointMarker m in markers)
|
||||
this.markers.Add(m);
|
||||
}
|
||||
|
||||
public CompositePointMarker(IEnumerable<PointMarker> markers) {
|
||||
if (markers == null)
|
||||
throw new ArgumentNullException("markers");
|
||||
foreach (PointMarker m in markers)
|
||||
this.markers.Add(m);
|
||||
}
|
||||
|
||||
|
||||
private readonly Collection<PointMarker> markers = new Collection<PointMarker>();
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
||||
public Collection<PointMarker> Markers {
|
||||
get { return markers; }
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext dc, Point screenPoint) {
|
||||
LocalValueEnumerator enumerator = GetLocalValueEnumerator();
|
||||
foreach (var marker in markers) {
|
||||
enumerator.Reset();
|
||||
while (enumerator.MoveNext()) {
|
||||
marker.SetValue(enumerator.Current.Property, enumerator.Current.Value);
|
||||
}
|
||||
|
||||
marker.Render(dc, screenPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
24
PointMarkers/DelegatePointMarker.cs
Normal file
24
PointMarkers/DelegatePointMarker.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.PointMarkers
|
||||
{
|
||||
/// <summary>Invokes specified delegate for rendering custon marker
|
||||
/// at every point of graph</summary>
|
||||
public sealed class DelegatePointMarker : PointMarker {
|
||||
public MarkerRenderHandler RenderCallback { get; set; }
|
||||
|
||||
public DelegatePointMarker() { }
|
||||
public DelegatePointMarker(MarkerRenderHandler renderCallback) {
|
||||
if (renderCallback == null)
|
||||
throw new ArgumentNullException("renderCallback");
|
||||
|
||||
RenderCallback = renderCallback;
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext dc, Point screenPoint) {
|
||||
RenderCallback(dc, screenPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
19
PointMarkers/ElementPointMarker.cs
Normal file
19
PointMarkers/ElementPointMarker.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.PointMarkers
|
||||
{
|
||||
/// <summary>Provides elements that represent markers along the graph</summary>
|
||||
public abstract class ElementPointMarker : DependencyObject {
|
||||
|
||||
/// <summary>Creates marker element at specified point</summary>
|
||||
/// <returns>UIElement representing marker</returns>
|
||||
public abstract UIElement CreateMarker();
|
||||
|
||||
public abstract void SetMarkerProperties(UIElement marker);
|
||||
|
||||
/// <summary>Moves specified marker so its center is located at specified screen point</summary>
|
||||
/// <param name="marker">UIElement created using CreateMarker</param>
|
||||
/// <param name="screenPoint">Point to center element around</param>
|
||||
public abstract void SetPosition(UIElement marker, Point screenPoint);
|
||||
}
|
||||
}
|
||||
26
PointMarkers/PointMarker.cs
Normal file
26
PointMarkers/PointMarker.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.PointMarkers
|
||||
{
|
||||
public delegate void MarkerRenderHandler(DrawingContext dc, Point screenPoint);
|
||||
|
||||
/// <summary>Renders markers along graph</summary>
|
||||
public abstract class PointMarker : DependencyObject {
|
||||
|
||||
/// <summary>Renders marker on screen</summary>
|
||||
/// <param name="dc">Drawing context to render marker on</param>
|
||||
/// <param name="dataPoint">Point from data source</param>
|
||||
/// <param name="screenPoint">Marker center coordinates on drawing context</param>
|
||||
public abstract void Render(DrawingContext dc, Point screenPoint);
|
||||
|
||||
public static implicit operator PointMarker(MarkerRenderHandler renderer) {
|
||||
return FromRenderer(renderer);
|
||||
}
|
||||
|
||||
public static PointMarker FromRenderer(MarkerRenderHandler renderer)
|
||||
{
|
||||
return new DelegatePointMarker(renderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
50
PointMarkers/RectElementPointMarker.cs
Normal file
50
PointMarkers/RectElementPointMarker.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.PointMarkers
|
||||
{
|
||||
/// <summary>Adds Circle element at every point of graph</summary>
|
||||
public class RectElementPointMarker : ShapeElementPointMarker {
|
||||
|
||||
public override UIElement CreateMarker()
|
||||
{
|
||||
Rectangle result = new Rectangle();
|
||||
result.Width = Size;
|
||||
result.Height = Size;
|
||||
result.Stroke = Brush;
|
||||
result.Fill = Fill;
|
||||
if (!String.IsNullOrEmpty(ToolTipText))
|
||||
{
|
||||
ToolTip tt = new ToolTip();
|
||||
tt.Content = ToolTipText;
|
||||
result.ToolTip = tt;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public override void SetMarkerProperties(UIElement marker)
|
||||
{
|
||||
Rectangle rect = (Rectangle)marker;
|
||||
|
||||
rect.Width = Size;
|
||||
rect.Height = Size;
|
||||
rect.Stroke = Brush;
|
||||
rect.Fill = Fill;
|
||||
|
||||
if (!String.IsNullOrEmpty(ToolTipText))
|
||||
{
|
||||
ToolTip tt = new ToolTip();
|
||||
tt.Content = ToolTipText;
|
||||
rect.ToolTip = tt;
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetPosition(UIElement marker, Point screenPoint)
|
||||
{
|
||||
Canvas.SetLeft(marker, screenPoint.X - Size / 2);
|
||||
Canvas.SetTop(marker, screenPoint.Y - Size / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
78
PointMarkers/ShapeElementPointMarker.cs
Normal file
78
PointMarkers/ShapeElementPointMarker.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.PointMarkers
|
||||
{
|
||||
/// <summary>Abstract class that extends ElementPointMarker and contains
|
||||
/// marker property as Pen, Brush and Size</summary>
|
||||
public abstract class ShapeElementPointMarker : ElementPointMarker {
|
||||
/// <summary>Size of marker in points</summary>
|
||||
public double Size {
|
||||
get { return (double)GetValue(SizeProperty); }
|
||||
set { SetValue(SizeProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SizeProperty =
|
||||
DependencyProperty.Register(
|
||||
"Size",
|
||||
typeof(double),
|
||||
typeof(ShapeElementPointMarker),
|
||||
new FrameworkPropertyMetadata(5.0));
|
||||
|
||||
/// <summary>Tooltip to show when cursor on over</summary>
|
||||
public string ToolTipText
|
||||
{
|
||||
get { return (string)GetValue(ToolTipTextProperty); }
|
||||
set { SetValue(ToolTipTextProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ToolTipTextProperty =
|
||||
DependencyProperty.Register(
|
||||
"ToolTipText",
|
||||
typeof(string),
|
||||
typeof(ShapeElementPointMarker),
|
||||
new FrameworkPropertyMetadata(String.Empty));
|
||||
|
||||
/// <summary>Pen to outline marker</summary>
|
||||
public Pen Pen {
|
||||
get { return (Pen)GetValue(PenProperty); }
|
||||
set { SetValue(PenProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty PenProperty =
|
||||
DependencyProperty.Register(
|
||||
"Pen",
|
||||
typeof(Pen),
|
||||
typeof(ShapeElementPointMarker),
|
||||
new FrameworkPropertyMetadata(null));
|
||||
|
||||
|
||||
public Brush Brush {
|
||||
get { return (Brush)GetValue(BrushProperty); }
|
||||
set { SetValue(BrushProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty BrushProperty =
|
||||
DependencyProperty.Register(
|
||||
"Brush",
|
||||
typeof(Brush),
|
||||
typeof(ShapeElementPointMarker),
|
||||
new FrameworkPropertyMetadata(Brushes.Red));
|
||||
|
||||
public Brush Fill
|
||||
{
|
||||
get { return (Brush)GetValue(FillProperty); }
|
||||
set { SetValue(FillProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty FillProperty =
|
||||
DependencyProperty.Register(
|
||||
"Fill",
|
||||
typeof(Brush),
|
||||
typeof(ShapeElementPointMarker),
|
||||
new FrameworkPropertyMetadata(Brushes.Red));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
49
PointMarkers/ShapePointMarker.cs
Normal file
49
PointMarkers/ShapePointMarker.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.PointMarkers
|
||||
{
|
||||
/// <summary>Abstract class that extends PointMarker and contains
|
||||
/// marker property as Pen, Brush and Size</summary>
|
||||
public abstract class ShapePointMarker : PointMarker {
|
||||
/// <summary>Size of marker in points</summary>
|
||||
public double Size {
|
||||
get { return (double)GetValue(SizeProperty); }
|
||||
set { SetValue(SizeProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SizeProperty =
|
||||
DependencyProperty.Register(
|
||||
"Size",
|
||||
typeof(double),
|
||||
typeof(ShapePointMarker),
|
||||
new FrameworkPropertyMetadata(5.0));
|
||||
|
||||
|
||||
/// <summary>Pen to outline marker</summary>
|
||||
public Pen Pen {
|
||||
get { return (Pen)GetValue(PenProperty); }
|
||||
set { SetValue(PenProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty PenProperty =
|
||||
DependencyProperty.Register(
|
||||
"Pen",
|
||||
typeof(Pen),
|
||||
typeof(ShapePointMarker),
|
||||
new FrameworkPropertyMetadata(null));
|
||||
|
||||
|
||||
public Brush Fill {
|
||||
get { return (Brush)GetValue(FillProperty); }
|
||||
set { SetValue(FillProperty, value); }
|
||||
}
|
||||
public static readonly DependencyProperty FillProperty =
|
||||
DependencyProperty.Register(
|
||||
"Fill",
|
||||
typeof(Brush),
|
||||
typeof(ShapePointMarker),
|
||||
new FrameworkPropertyMetadata(Brushes.Red)
|
||||
);
|
||||
}
|
||||
}
|
||||
49
PointMarkers/TrianglePointMarker.cs
Normal file
49
PointMarkers/TrianglePointMarker.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.PointMarkers
|
||||
{
|
||||
/// <summary>Class that renders triangular marker at every point of graph</summary>
|
||||
public class TrianglePointMarker : ShapePointMarker
|
||||
{
|
||||
public override void Render(DrawingContext dc, Point screenPoint)
|
||||
{
|
||||
Point? pt0 = null;
|
||||
Point? pt1 = null;
|
||||
Point? pt2 = null;
|
||||
|
||||
if (Orientation.Equals("up"))
|
||||
{
|
||||
pt0 = Point.Add(screenPoint, new Vector(-Size / 2, Size / 2));
|
||||
pt1 = Point.Add(screenPoint, new Vector(0, -Size / 2));
|
||||
pt2 = Point.Add(screenPoint, new Vector(Size / 2, Size / 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
pt0 = Point.Add(screenPoint, new Vector(-Size / 2, -Size / 2));
|
||||
pt1 = Point.Add(screenPoint, new Vector(0, Size / 2));
|
||||
pt2 = Point.Add(screenPoint, new Vector(Size / 2, -Size / 2));
|
||||
}
|
||||
StreamGeometry streamGeom = new StreamGeometry();
|
||||
using (var context = streamGeom.Open()) {
|
||||
context.BeginFigure(pt0.Value, true, true);
|
||||
context.LineTo(pt1.Value, true, true);
|
||||
context.LineTo(pt2.Value, true, true);
|
||||
}
|
||||
dc.DrawGeometry(Fill, Pen, streamGeom);
|
||||
}
|
||||
public String Orientation
|
||||
{
|
||||
get { return (String)GetValue(OrientationProperty); }
|
||||
set { SetValue(OrientationProperty, value); }
|
||||
}
|
||||
public static readonly DependencyProperty OrientationProperty =
|
||||
DependencyProperty.Register(
|
||||
"Orientation",
|
||||
typeof(String),
|
||||
typeof(TrianglePointMarker),
|
||||
new FrameworkPropertyMetadata("up")
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user