167
Source/OxyPlot.WindowsForms/DrawingConverterExtensions.cs
Normal file
167
Source/OxyPlot.WindowsForms/DrawingConverterExtensions.cs
Normal file
@@ -0,0 +1,167 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="ConverterExtensions.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Extension method used to convert to/from Windows/Windows.Media classes.
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#if OXYPLOT_COREDRAWING
|
||||
namespace OxyPlot.Core.Drawing
|
||||
#else
|
||||
namespace OxyPlot.WindowsForms
|
||||
#endif
|
||||
{
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
/// <summary>
|
||||
/// Extension method used to convert to/from Windows/Windows.Media classes.
|
||||
/// </summary>
|
||||
public static class DrawingConverterExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Calculate the distance between two points.
|
||||
/// </summary>
|
||||
/// <param name="p1">The first point.</param>
|
||||
/// <param name="p2">The second point.</param>
|
||||
/// <returns>The distance.</returns>
|
||||
public static double DistanceTo(this Point p1, Point p2)
|
||||
{
|
||||
double dx = p1.X - p2.X;
|
||||
double dy = p1.Y - p2.Y;
|
||||
return Math.Sqrt((dx * dx) + (dy * dy));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a color to a Brush.
|
||||
/// </summary>
|
||||
/// <param name="c">The color.</param>
|
||||
/// <returns>A SolidColorBrush.</returns>
|
||||
public static Brush ToBrush(this OxyColor c)
|
||||
{
|
||||
return new SolidBrush(c.ToColor());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an OxyColor to a Color.
|
||||
/// </summary>
|
||||
/// <param name="c">The color.</param>
|
||||
/// <returns>A Color.</returns>
|
||||
public static Color ToColor(this OxyColor c)
|
||||
{
|
||||
return Color.FromArgb(c.A, c.R, c.G, c.B);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a HorizontalAlignment to a HorizontalTextAlign.
|
||||
/// </summary>
|
||||
/// <param name="alignment">The alignment.</param>
|
||||
/// <returns>A HorizontalTextAlign.</returns>
|
||||
public static OxyPlot.HorizontalAlignment ToHorizontalTextAlign(this HorizontalAlignment alignment)
|
||||
{
|
||||
switch (alignment)
|
||||
{
|
||||
case HorizontalAlignment.Center:
|
||||
return OxyPlot.HorizontalAlignment.Center;
|
||||
case HorizontalAlignment.Right:
|
||||
return OxyPlot.HorizontalAlignment.Right;
|
||||
default:
|
||||
return OxyPlot.HorizontalAlignment.Left;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="Color" /> to an <see cref="OxyColor" />.
|
||||
/// </summary>
|
||||
/// <param name="color">The color to convert.</param>
|
||||
/// <returns>An <see cref="OxyColor" />.</returns>
|
||||
public static OxyColor ToOxyColor(this Color color)
|
||||
{
|
||||
return OxyColor.FromArgb(color.A, color.R, color.G, color.B);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="Brush" /> to an <see cref="OxyColor" />.
|
||||
/// </summary>
|
||||
/// <param name="brush">The brush to convert.</param>
|
||||
/// <returns>An <see cref="OxyColor" />.</returns>
|
||||
public static OxyColor ToOxyColor(this Brush brush)
|
||||
{
|
||||
var scb = brush as SolidBrush;
|
||||
return scb != null ? scb.Color.ToOxyColor() : OxyColors.Undefined;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Thickness to an OxyThickness.
|
||||
/// </summary>
|
||||
/// <param name="pt">The screen point.</param>
|
||||
/// <param name="aliased">use pixel alignment conversion if set to <c>true</c>.</param>
|
||||
/// <returns>An OxyPlot thickness.</returns>
|
||||
public static Point ToPoint(this ScreenPoint pt, bool aliased)
|
||||
{
|
||||
// adding 0.5 to get pixel boundary alignment, seems to work
|
||||
// http://weblogs.asp.net/mschwarz/archive/2008/01/04/silverlight-rectangles-paths-and-line-comparison.aspx
|
||||
// http://www.wynapse.com/Silverlight/Tutor/Silverlight_Rectangles_Paths_And_Lines_Comparison.aspx
|
||||
if (aliased)
|
||||
{
|
||||
return new Point((int)pt.X, (int)pt.Y);
|
||||
}
|
||||
|
||||
return new Point((int)Math.Round(pt.X), (int)Math.Round(pt.Y));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an <see cref="OxyRect" /> to a <see cref="Rectangle" />.
|
||||
/// </summary>
|
||||
/// <param name="r">The rectangle.</param>
|
||||
/// <param name="aliased">use pixel alignment if set to <c>true</c>.</param>
|
||||
/// <returns>A <see cref="Rectangle" />.</returns>
|
||||
public static Rectangle ToRect(this OxyRect r, bool aliased)
|
||||
{
|
||||
if (aliased)
|
||||
{
|
||||
var x = (int)r.Left;
|
||||
var y = (int)r.Top;
|
||||
var ri = (int)r.Right;
|
||||
var bo = (int)r.Bottom;
|
||||
return new Rectangle(x, y, ri - x, bo - y);
|
||||
}
|
||||
|
||||
return new Rectangle(
|
||||
(int)Math.Round(r.Left), (int)Math.Round(r.Top), (int)Math.Round(r.Width), (int)Math.Round(r.Height));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a point to a ScreenPoint.
|
||||
/// </summary>
|
||||
/// <param name="pt">The point.</param>
|
||||
/// <returns>A screen point.</returns>
|
||||
public static ScreenPoint ToScreenPoint(this Point pt)
|
||||
{
|
||||
return new ScreenPoint(pt.X, pt.Y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Point array to a ScreenPoint array.
|
||||
/// </summary>
|
||||
/// <param name="points">The points.</param>
|
||||
/// <returns>A ScreenPoint array.</returns>
|
||||
public static ScreenPoint[] ToScreenPointArray(this Point[] points)
|
||||
{
|
||||
if (points == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var pts = new ScreenPoint[points.Length];
|
||||
for (int i = 0; i < points.Length; i++)
|
||||
{
|
||||
pts[i] = points[i].ToScreenPoint();
|
||||
}
|
||||
|
||||
return pts;
|
||||
}
|
||||
}
|
||||
}
|
||||
37
Source/OxyPlot.WindowsForms/ExporterExtensions.cs
Normal file
37
Source/OxyPlot.WindowsForms/ExporterExtensions.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="ExporterExtensions.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Provides extension methods for exporters.
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#if OXYPLOT_COREDRAWING
|
||||
namespace OxyPlot.Core.Drawing
|
||||
#else
|
||||
namespace OxyPlot.WindowsForms
|
||||
#endif
|
||||
{
|
||||
using System.IO;
|
||||
|
||||
/// <summary>
|
||||
/// Provides extension methods for exporters.
|
||||
/// </summary>
|
||||
public static class ExporterExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Exports the specified <see cref="PlotModel" /> to a file.
|
||||
/// </summary>
|
||||
/// <param name="exporter">The exporter.</param>
|
||||
/// <param name="model">The model to export.</param>
|
||||
/// <param name="path">The path to the file.</param>
|
||||
public static void ExportToFile(this IExporter exporter, IPlotModel model, string path)
|
||||
{
|
||||
using (var stream = File.OpenWrite(path))
|
||||
{
|
||||
exporter.Export(model, stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
168
Source/OxyPlot.WindowsForms/GraphicsPenDescription.cs
Normal file
168
Source/OxyPlot.WindowsForms/GraphicsPenDescription.cs
Normal file
@@ -0,0 +1,168 @@
|
||||
|
||||
#if OXYPLOT_COREDRAWING
|
||||
namespace OxyPlot.Core.Drawing
|
||||
#else
|
||||
namespace OxyPlot.WindowsForms
|
||||
#endif
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
/// <summary>
|
||||
/// Describes a GDI+ Pen.
|
||||
/// </summary>
|
||||
public class GraphicsPenDescription
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GraphicsPenDescription" /> class.
|
||||
/// </summary>
|
||||
/// <param name="color">The color.</param>
|
||||
/// <param name="thickness">The thickness.</param>
|
||||
/// <param name="dashArray">The dash array.</param>
|
||||
/// <param name="lineJoin">The line join.</param>
|
||||
public GraphicsPenDescription(OxyColor color, double thickness, double[] dashArray = null, OxyPlot.LineJoin lineJoin = OxyPlot.LineJoin.Miter)
|
||||
{
|
||||
Color = color;
|
||||
Thickness = thickness;
|
||||
DashArray = dashArray;
|
||||
LineJoin = lineJoin;
|
||||
|
||||
cachedHashCode = ComputeHashCode();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color of the pen.
|
||||
/// </summary>
|
||||
/// <value>The color.</value>
|
||||
public OxyColor Color { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the line thickness.
|
||||
/// </summary>
|
||||
/// <value>The line thickness.</value>
|
||||
public double Thickness { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the dash array.
|
||||
/// </summary>
|
||||
/// <value>The dash array.</value>
|
||||
public double[] DashArray { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the line join type.
|
||||
/// </summary>
|
||||
/// <value>The line join type.</value>
|
||||
public LineJoin LineJoin { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The HashCode of the <see cref="GraphicsPenDescription" /> instance, as computed in the constructor.
|
||||
/// </summary>
|
||||
private readonly int cachedHashCode;
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified <see cref="System.Object" /> is equal to this instance.
|
||||
/// </summary>
|
||||
/// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param>
|
||||
/// <returns><c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c> .</returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var description = obj as GraphicsPenDescription;
|
||||
|
||||
return description != null &&
|
||||
Color.Equals(description.Color) &&
|
||||
Thickness == description.Thickness &&
|
||||
DashArraysEquals(DashArray, description.DashArray) &&
|
||||
LineJoin == description.LineJoin;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a hash code for this instance.
|
||||
/// </summary>
|
||||
/// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return cachedHashCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the HashCode for the instance.
|
||||
/// </summary>
|
||||
/// <returns>The HashCode for the instance.</returns>
|
||||
private int ComputeHashCode()
|
||||
{
|
||||
var hashCode = 754997215;
|
||||
|
||||
unchecked
|
||||
{
|
||||
hashCode = hashCode * -1521134295 + Color.GetHashCode();
|
||||
hashCode = hashCode * -1521134295 + Thickness.GetHashCode();
|
||||
hashCode = hashCode * -1521134295 + ComputeDashArrayHashCode(DashArray);
|
||||
hashCode = hashCode * -1521134295 + LineJoin.GetHashCode();
|
||||
}
|
||||
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes a HashCode for the given array based on every element in the array.
|
||||
/// </summary>
|
||||
/// <param name="array">The array</param>
|
||||
/// <returns>A HashCode</returns>
|
||||
private static int ComputeDashArrayHashCode(double[] array)
|
||||
{
|
||||
if (array == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int hashCode = array.Length;
|
||||
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
hashCode = hashCode * 31 + array[i].GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether two arrays are equivalent.
|
||||
/// </summary>
|
||||
/// <param name="l">The left array.</param>
|
||||
/// <param name="r">The right array.</param>
|
||||
/// <returns><c>true</c> if the arrays are the same array, are both null, or have the same elements; otherwise <c>false</c></returns>
|
||||
private static bool DashArraysEquals(double[] l, double[] r)
|
||||
{
|
||||
if (l == r)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (l == null || r == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (l.Length != r.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < l.Length; i++)
|
||||
{
|
||||
if (l[i] != r[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
581
Source/OxyPlot.WindowsForms/GraphicsRenderContext.cs
Normal file
581
Source/OxyPlot.WindowsForms/GraphicsRenderContext.cs
Normal file
@@ -0,0 +1,581 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="GraphicsRenderContext.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// The graphics render context.
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#if OXYPLOT_COREDRAWING
|
||||
namespace OxyPlot.Core.Drawing
|
||||
#else
|
||||
namespace OxyPlot.WindowsForms
|
||||
#endif
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Drawing.Text;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using OxyPlot;
|
||||
|
||||
/// <summary>
|
||||
/// The graphics render context.
|
||||
/// </summary>
|
||||
public class GraphicsRenderContext : ClippingRenderContext, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// The font size factor.
|
||||
/// </summary>
|
||||
private const float FontsizeFactor = 0.8f;
|
||||
|
||||
/// <summary>
|
||||
/// The images in use
|
||||
/// </summary>
|
||||
private readonly HashSet<OxyImage> imagesInUse = new HashSet<OxyImage>();
|
||||
|
||||
/// <summary>
|
||||
/// The image cache
|
||||
/// </summary>
|
||||
private readonly Dictionary<OxyImage, Image> imageCache = new Dictionary<OxyImage, Image>();
|
||||
|
||||
/// <summary>
|
||||
/// The brush cache.
|
||||
/// </summary>
|
||||
private readonly Dictionary<OxyColor, Brush> brushes = new Dictionary<OxyColor, Brush>();
|
||||
|
||||
/// <summary>
|
||||
/// The pen cache.
|
||||
/// </summary>
|
||||
private readonly Dictionary<GraphicsPenDescription, Pen> pens = new Dictionary<GraphicsPenDescription, Pen>();
|
||||
|
||||
/// <summary>
|
||||
/// The string format.
|
||||
/// </summary>
|
||||
private readonly StringFormat stringFormat;
|
||||
|
||||
/// <summary>
|
||||
/// The GDI+ drawing surface.
|
||||
/// </summary>
|
||||
private Graphics g;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GraphicsRenderContext" /> class.
|
||||
/// </summary>
|
||||
/// <param name="graphics">The drawing surface.</param>
|
||||
public GraphicsRenderContext(Graphics graphics = null)
|
||||
{
|
||||
this.g = graphics;
|
||||
if (this.g != null)
|
||||
{
|
||||
this.g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
|
||||
}
|
||||
|
||||
this.stringFormat = StringFormat.GenericTypographic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the graphics target.
|
||||
/// </summary>
|
||||
/// <param name="graphics">The graphics surface.</param>
|
||||
public void SetGraphicsTarget(Graphics graphics)
|
||||
{
|
||||
this.g = graphics;
|
||||
this.g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void DrawEllipse(OxyRect rect, OxyColor fill, OxyColor stroke, double thickness, EdgeRenderingMode edgeRenderingMode)
|
||||
{
|
||||
var isStroked = stroke.IsVisible() && thickness > 0;
|
||||
|
||||
this.SetSmoothingMode(this.ShouldUseAntiAliasingForEllipse(edgeRenderingMode));
|
||||
|
||||
if (fill.IsVisible())
|
||||
{
|
||||
this.g.FillEllipse(this.GetCachedBrush(fill), (float)rect.Left, (float)rect.Top, (float)rect.Width, (float)rect.Height);
|
||||
}
|
||||
|
||||
if (!isStroked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var pen = this.GetCachedPen(stroke, thickness);
|
||||
this.g.DrawEllipse(pen, (float)rect.Left, (float)rect.Top, (float)rect.Width, (float)rect.Height);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void DrawLine(
|
||||
IList<ScreenPoint> points,
|
||||
OxyColor stroke,
|
||||
double thickness,
|
||||
EdgeRenderingMode edgeRenderingMode,
|
||||
double[] dashArray,
|
||||
OxyPlot.LineJoin lineJoin)
|
||||
{
|
||||
if (stroke.IsInvisible() || thickness <= 0 || points.Count < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.SetSmoothingMode(this.ShouldUseAntiAliasingForLine(edgeRenderingMode, points));
|
||||
|
||||
var pen = this.GetCachedPen(stroke, thickness, dashArray, lineJoin);
|
||||
this.g.DrawLines(pen, this.ToPoints(points));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void DrawPolygon(
|
||||
IList<ScreenPoint> points,
|
||||
OxyColor fill,
|
||||
OxyColor stroke,
|
||||
double thickness,
|
||||
EdgeRenderingMode edgeRenderingMode,
|
||||
double[] dashArray,
|
||||
OxyPlot.LineJoin lineJoin)
|
||||
{
|
||||
if (points.Count < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.SetSmoothingMode(this.ShouldUseAntiAliasingForLine(edgeRenderingMode, points));
|
||||
|
||||
var pts = this.ToPoints(points);
|
||||
if (fill.IsVisible())
|
||||
{
|
||||
this.g.FillPolygon(this.GetCachedBrush(fill), pts);
|
||||
}
|
||||
|
||||
if (stroke.IsInvisible() || thickness <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var pen = this.GetCachedPen(stroke, thickness, dashArray, lineJoin);
|
||||
this.g.DrawPolygon(pen, pts);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void DrawRectangle(OxyRect rect, OxyColor fill, OxyColor stroke, double thickness, EdgeRenderingMode edgeRenderingMode)
|
||||
{
|
||||
this.SetSmoothingMode(this.ShouldUseAntiAliasingForRect(edgeRenderingMode));
|
||||
|
||||
if (fill.IsVisible())
|
||||
{
|
||||
this.g.FillRectangle(
|
||||
this.GetCachedBrush(fill), (float)rect.Left, (float)rect.Top, (float)rect.Width, (float)rect.Height);
|
||||
}
|
||||
|
||||
if (stroke.IsInvisible() || thickness <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var pen = this.GetCachedPen(stroke, thickness);
|
||||
this.g.DrawRectangle(pen, (float)rect.Left, (float)rect.Top, (float)rect.Width, (float)rect.Height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the text.
|
||||
/// </summary>
|
||||
/// <param name="p">The p.</param>
|
||||
/// <param name="text">The text.</param>
|
||||
/// <param name="fill">The fill color.</param>
|
||||
/// <param name="fontFamily">The font family.</param>
|
||||
/// <param name="fontSize">Size of the font.</param>
|
||||
/// <param name="fontWeight">The font weight.</param>
|
||||
/// <param name="rotate">The rotation angle.</param>
|
||||
/// <param name="halign">The horizontal alignment.</param>
|
||||
/// <param name="valign">The vertical alignment.</param>
|
||||
/// <param name="maxSize">The maximum size of the text.</param>
|
||||
public override void DrawText(
|
||||
ScreenPoint p,
|
||||
string text,
|
||||
OxyColor fill,
|
||||
string fontFamily,
|
||||
double fontSize,
|
||||
double fontWeight,
|
||||
double rotate,
|
||||
HorizontalAlignment halign,
|
||||
VerticalAlignment valign,
|
||||
OxySize? maxSize)
|
||||
{
|
||||
if (text == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var fontStyle = fontWeight < 700 ? FontStyle.Regular : FontStyle.Bold;
|
||||
|
||||
using (var font = CreateFont(fontFamily, fontSize, fontStyle))
|
||||
{
|
||||
this.stringFormat.Alignment = StringAlignment.Near;
|
||||
this.stringFormat.LineAlignment = StringAlignment.Near;
|
||||
var size = Ceiling(this.g.MeasureString(text, font, int.MaxValue, this.stringFormat));
|
||||
if (maxSize != null)
|
||||
{
|
||||
if (size.Width > maxSize.Value.Width)
|
||||
{
|
||||
size.Width = (float)maxSize.Value.Width;
|
||||
}
|
||||
|
||||
if (size.Height > maxSize.Value.Height)
|
||||
{
|
||||
size.Height = (float)maxSize.Value.Height;
|
||||
}
|
||||
}
|
||||
|
||||
float dx = 0;
|
||||
if (halign == HorizontalAlignment.Center)
|
||||
{
|
||||
dx = -size.Width / 2;
|
||||
}
|
||||
|
||||
if (halign == HorizontalAlignment.Right)
|
||||
{
|
||||
dx = -size.Width;
|
||||
}
|
||||
|
||||
float dy = 0;
|
||||
this.stringFormat.LineAlignment = StringAlignment.Near;
|
||||
if (valign == VerticalAlignment.Middle)
|
||||
{
|
||||
dy = -size.Height / 2;
|
||||
}
|
||||
|
||||
if (valign == VerticalAlignment.Bottom)
|
||||
{
|
||||
dy = -size.Height;
|
||||
}
|
||||
|
||||
var graphicsState = this.g.Save();
|
||||
|
||||
this.g.TranslateTransform((float)p.X, (float)p.Y);
|
||||
|
||||
var layoutRectangle = new RectangleF(0, 0, size.Width, size.Height);
|
||||
if (Math.Abs(rotate) > double.Epsilon)
|
||||
{
|
||||
this.g.RotateTransform((float)rotate);
|
||||
|
||||
layoutRectangle.Height += (float)(fontSize / 18.0);
|
||||
}
|
||||
|
||||
this.g.TranslateTransform(dx, dy);
|
||||
|
||||
this.g.DrawString(text, font, this.GetCachedBrush(fill), layoutRectangle, this.stringFormat);
|
||||
|
||||
this.g.Restore(graphicsState);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Measures the text.
|
||||
/// </summary>
|
||||
/// <param name="text">The text.</param>
|
||||
/// <param name="fontFamily">The font family.</param>
|
||||
/// <param name="fontSize">Size of the font.</param>
|
||||
/// <param name="fontWeight">The font weight.</param>
|
||||
/// <returns>The text size.</returns>
|
||||
public override OxySize MeasureText(string text, string fontFamily, double fontSize, double fontWeight)
|
||||
{
|
||||
if (text == null)
|
||||
{
|
||||
return OxySize.Empty;
|
||||
}
|
||||
|
||||
var fontStyle = fontWeight < 700 ? FontStyle.Regular : FontStyle.Bold;
|
||||
using (var font = CreateFont(fontFamily, fontSize, fontStyle))
|
||||
{
|
||||
this.stringFormat.Alignment = StringAlignment.Near;
|
||||
this.stringFormat.LineAlignment = StringAlignment.Near;
|
||||
var size = Ceiling(this.g.MeasureString(text, font, int.MaxValue, this.stringFormat));
|
||||
return new OxySize(size.Width, size.Height);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleans up resources not in use.
|
||||
/// </summary>
|
||||
/// <remarks>This method is called at the end of each rendering.</remarks>
|
||||
public override void CleanUp()
|
||||
{
|
||||
var imagesToRelease = this.imageCache.Keys.Where(i => !this.imagesInUse.Contains(i)).ToList();
|
||||
foreach (var i in imagesToRelease)
|
||||
{
|
||||
var image = this.GetImage(i);
|
||||
image.Dispose();
|
||||
this.imageCache.Remove(i);
|
||||
}
|
||||
|
||||
this.imagesInUse.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the image.
|
||||
/// </summary>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="srcX">The source executable.</param>
|
||||
/// <param name="srcY">The source asynchronous.</param>
|
||||
/// <param name="srcWidth">Width of the source.</param>
|
||||
/// <param name="srcHeight">Height of the source.</param>
|
||||
/// <param name="x">The executable.</param>
|
||||
/// <param name="y">The asynchronous.</param>
|
||||
/// <param name="w">The forward.</param>
|
||||
/// <param name="h">The authentication.</param>
|
||||
/// <param name="opacity">The opacity.</param>
|
||||
/// <param name="interpolate">if set to <c>true</c> [interpolate].</param>
|
||||
public override void DrawImage(OxyImage source, double srcX, double srcY, double srcWidth, double srcHeight, double x, double y, double w, double h, double opacity, bool interpolate)
|
||||
{
|
||||
var image = this.GetImage(source);
|
||||
if (image != null)
|
||||
{
|
||||
ImageAttributes ia = null;
|
||||
if (opacity < 1)
|
||||
{
|
||||
var cm = new ColorMatrix
|
||||
{
|
||||
Matrix00 = 1f,
|
||||
Matrix11 = 1f,
|
||||
Matrix22 = 1f,
|
||||
Matrix33 = (float)opacity,
|
||||
Matrix44 = 1f
|
||||
};
|
||||
|
||||
ia = new ImageAttributes();
|
||||
ia.SetColorMatrix(cm, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
|
||||
}
|
||||
|
||||
this.g.InterpolationMode = interpolate ? InterpolationMode.HighQualityBicubic : InterpolationMode.NearestNeighbor;
|
||||
int sx = (int)Math.Floor(x);
|
||||
int sy = (int)Math.Floor(y);
|
||||
int sw = (int)Math.Ceiling(x + w) - sx;
|
||||
int sh = (int)Math.Ceiling(y + h) - sy;
|
||||
var destRect = new Rectangle(sx, sy, sw, sh);
|
||||
this.g.DrawImage(image, destRect, (float)srcX - 0.5f, (float)srcY - 0.5f, (float)srcWidth, (float)srcHeight, GraphicsUnit.Pixel, ia);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetClip(OxyRect rect)
|
||||
{
|
||||
this.g.SetClip(rect.ToRect(false));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void ResetClip()
|
||||
{
|
||||
this.g.ResetClip();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
// dispose images
|
||||
foreach (var i in this.imageCache)
|
||||
{
|
||||
i.Value.Dispose();
|
||||
}
|
||||
this.imageCache.Clear();
|
||||
|
||||
// dispose pens, brushes etc.
|
||||
this.stringFormat.Dispose();
|
||||
|
||||
foreach (var brush in this.brushes.Values)
|
||||
{
|
||||
brush.Dispose();
|
||||
}
|
||||
this.brushes.Clear();
|
||||
|
||||
foreach (var pen in this.pens.Values)
|
||||
{
|
||||
pen.Dispose();
|
||||
}
|
||||
this.pens.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a font.
|
||||
/// </summary>
|
||||
/// <param name="fontFamily">The font family.</param>
|
||||
/// <param name="fontSize">Size of the font.</param>
|
||||
/// <param name="fontStyle">The font style.</param>
|
||||
/// <returns>A font</returns>
|
||||
private static Font CreateFont(string fontFamily, double fontSize, FontStyle fontStyle)
|
||||
{
|
||||
return new Font(fontFamily, (float)fontSize * FontsizeFactor, fontStyle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the ceiling of the given <see cref="SizeF"/> as a <see cref="SizeF"/>.
|
||||
/// </summary>
|
||||
/// <param name="size">The size.</param>
|
||||
/// <returns>A <see cref="SizeF"/>.</returns>
|
||||
private static SizeF Ceiling(SizeF size)
|
||||
{
|
||||
var ceiling = Size.Ceiling(size);
|
||||
return new SizeF(ceiling.Width, ceiling.Height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the image from the specified source.
|
||||
/// </summary>
|
||||
/// <param name="source">The image source.</param>
|
||||
/// <returns>A <see cref="Image" />.</returns>
|
||||
private Image GetImage(OxyImage source)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!this.imagesInUse.Contains(source))
|
||||
{
|
||||
this.imagesInUse.Add(source);
|
||||
}
|
||||
|
||||
Image src;
|
||||
if (this.imageCache.TryGetValue(source, out src))
|
||||
{
|
||||
return src;
|
||||
}
|
||||
|
||||
Image btm;
|
||||
using (var ms = new MemoryStream(source.GetData()))
|
||||
{
|
||||
btm = Image.FromStream(ms);
|
||||
}
|
||||
|
||||
this.imageCache.Add(source, btm);
|
||||
return btm;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cached brush.
|
||||
/// </summary>
|
||||
/// <param name="fill">The fill color.</param>
|
||||
/// <returns>A <see cref="Brush" />.</returns>
|
||||
private Brush GetCachedBrush(OxyColor fill)
|
||||
{
|
||||
Brush brush;
|
||||
if (this.brushes.TryGetValue(fill, out brush))
|
||||
{
|
||||
return brush;
|
||||
}
|
||||
|
||||
return this.brushes[fill] = fill.ToBrush();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cached pen.
|
||||
/// </summary>
|
||||
/// <param name="stroke">The stroke color.</param>
|
||||
/// <param name="thickness">The thickness.</param>
|
||||
/// <param name="dashArray">The dash array.</param>
|
||||
/// <param name="lineJoin">The line join.</param>
|
||||
/// <returns>A <see cref="Pen" />.</returns>
|
||||
private Pen GetCachedPen(OxyColor stroke, double thickness, double[] dashArray = null, OxyPlot.LineJoin lineJoin = OxyPlot.LineJoin.Miter)
|
||||
{
|
||||
GraphicsPenDescription description = new GraphicsPenDescription(stroke, thickness, dashArray, lineJoin);
|
||||
|
||||
Pen pen;
|
||||
if (this.pens.TryGetValue(description, out pen))
|
||||
{
|
||||
return pen;
|
||||
}
|
||||
|
||||
return this.pens[description] = CreatePen(stroke, thickness, dashArray, lineJoin);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a pen.
|
||||
/// </summary>
|
||||
/// <param name="stroke">The stroke.</param>
|
||||
/// <param name="thickness">The thickness.</param>
|
||||
/// <param name="dashArray">The dash array.</param>
|
||||
/// <param name="lineJoin">The line join.</param>
|
||||
/// <returns>A <see cref="Pen" />.</returns>
|
||||
private Pen CreatePen(OxyColor stroke, double thickness, double[] dashArray = null, OxyPlot.LineJoin lineJoin = OxyPlot.LineJoin.Miter)
|
||||
{
|
||||
var pen = new Pen(stroke.ToColor(), (float)thickness);
|
||||
|
||||
if (dashArray != null)
|
||||
{
|
||||
pen.DashPattern = this.ToFloatArray(dashArray);
|
||||
}
|
||||
|
||||
switch (lineJoin)
|
||||
{
|
||||
case OxyPlot.LineJoin.Round:
|
||||
pen.LineJoin = System.Drawing.Drawing2D.LineJoin.Round;
|
||||
break;
|
||||
case OxyPlot.LineJoin.Bevel:
|
||||
pen.LineJoin = System.Drawing.Drawing2D.LineJoin.Bevel;
|
||||
break;
|
||||
// The default LineJoin is Miter
|
||||
}
|
||||
|
||||
return pen;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the smoothing mode.
|
||||
/// </summary>
|
||||
/// <param name="useAntiAliasing">A value indicating whether to use Anti-Aliasing.</param>
|
||||
private void SetSmoothingMode(bool useAntiAliasing)
|
||||
{
|
||||
this.g.SmoothingMode = useAntiAliasing ? SmoothingMode.HighQuality : SmoothingMode.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a double array to a float array.
|
||||
/// </summary>
|
||||
/// <param name="a">The a.</param>
|
||||
/// <returns>The float array.</returns>
|
||||
private float[] ToFloatArray(double[] a)
|
||||
{
|
||||
if (a == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var r = new float[a.Length];
|
||||
for (int i = 0; i < a.Length; i++)
|
||||
{
|
||||
r[i] = (float)a[i];
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a list of point to an array of PointF.
|
||||
/// </summary>
|
||||
/// <param name="points">The points.</param>
|
||||
/// <returns>An array of points.</returns>
|
||||
private PointF[] ToPoints(IList<ScreenPoint> points)
|
||||
{
|
||||
if (points == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var r = new PointF[points.Count()];
|
||||
int i = 0;
|
||||
foreach (ScreenPoint p in points)
|
||||
{
|
||||
r[i++] = new PointF((float)p.X, (float)p.Y);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
19
Source/OxyPlot.WindowsForms/OxyPlot.WindowsForms.csproj
Normal file
19
Source/OxyPlot.WindowsForms/OxyPlot.WindowsForms.csproj
Normal file
@@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net462;net6.0-windows;net7.0-windows</TargetFrameworks>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<Description>OxyPlot is a plotting library for .NET. This package targets Windows Forms applications.</Description>
|
||||
<PackageTags>plotting plot charting chart</PackageTags>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||
<SignAssembly>True</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>OxyPlot.WindowsForms.snk</AssemblyOriginatorKeyFile>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OxyPlot\OxyPlot.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="OxyPlot.WindowsForms.snk" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,2 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=Utilities/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
BIN
Source/OxyPlot.WindowsForms/OxyPlot.WindowsForms.snk
Normal file
BIN
Source/OxyPlot.WindowsForms/OxyPlot.WindowsForms.snk
Normal file
Binary file not shown.
39
Source/OxyPlot.WindowsForms/PlotModelExtensions.cs
Normal file
39
Source/OxyPlot.WindowsForms/PlotModelExtensions.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="PlotModelExtensions.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Provides extension methods to the <see cref="PlotModel" />.
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace OxyPlot.WindowsForms
|
||||
{
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
/// <summary>
|
||||
/// Provides extension methods to the <see cref="PlotModel" />.
|
||||
/// </summary>
|
||||
public static class PlotModelExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates an SVG string.
|
||||
/// </summary>
|
||||
/// <param name="model">The model.</param>
|
||||
/// <param name="width">The width (points).</param>
|
||||
/// <param name="height">The height (points).</param>
|
||||
/// <param name="isDocument">if set to <c>true</c>, the xml headers will be included (?xml and !DOCTYPE).</param>
|
||||
/// <returns>A <see cref="string" />.</returns>
|
||||
public static string ToSvg(this PlotModel model, double width, double height, bool isDocument)
|
||||
{
|
||||
using (var g = Graphics.FromHwnd(IntPtr.Zero))
|
||||
{
|
||||
using (var rc = new GraphicsRenderContext(g) { RendersToScreen = false })
|
||||
{
|
||||
return OxyPlot.SvgExporter.ExportToString(model, width, height, isDocument, rc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
575
Source/OxyPlot.WindowsForms/PlotView.cs
Normal file
575
Source/OxyPlot.WindowsForms/PlotView.cs
Normal file
@@ -0,0 +1,575 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="PlotView.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Represents a control that displays a <see cref="PlotModel" />.
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace OxyPlot.WindowsForms
|
||||
{
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a control that displays a <see cref="PlotModel" />.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class PlotView : Control, IPlotView
|
||||
{
|
||||
/// <summary>
|
||||
/// The category for the properties of this control.
|
||||
/// </summary>
|
||||
private const string OxyPlotCategory = "OxyPlot";
|
||||
|
||||
/// <summary>
|
||||
/// The invalidate lock.
|
||||
/// </summary>
|
||||
private readonly object invalidateLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// The model lock.
|
||||
/// </summary>
|
||||
private readonly object modelLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// The rendering lock.
|
||||
/// </summary>
|
||||
private readonly object renderingLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// The render context.
|
||||
/// </summary>
|
||||
private readonly GraphicsRenderContext renderContext;
|
||||
|
||||
/// <summary>
|
||||
/// The tracker label.
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
private Label trackerLabel;
|
||||
|
||||
/// <summary>
|
||||
/// The current model (holding a reference to this plot view).
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
private PlotModel currentModel;
|
||||
|
||||
/// <summary>
|
||||
/// The is model invalidated.
|
||||
/// </summary>
|
||||
private bool isModelInvalidated;
|
||||
|
||||
/// <summary>
|
||||
/// The model.
|
||||
/// </summary>
|
||||
private PlotModel model;
|
||||
|
||||
/// <summary>
|
||||
/// The default controller.
|
||||
/// </summary>
|
||||
private IPlotController defaultController;
|
||||
|
||||
/// <summary>
|
||||
/// The update data flag.
|
||||
/// </summary>
|
||||
private bool updateDataFlag = true;
|
||||
|
||||
/// <summary>
|
||||
/// The zoom rectangle.
|
||||
/// </summary>
|
||||
private Rectangle zoomRectangle;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PlotView" /> class.
|
||||
/// </summary>
|
||||
public PlotView()
|
||||
{
|
||||
this.renderContext = new GraphicsRenderContext();
|
||||
|
||||
// ReSharper disable DoNotCallOverridableMethodsInConstructor
|
||||
this.DoubleBuffered = true;
|
||||
// ReSharper restore DoNotCallOverridableMethodsInConstructor
|
||||
this.PanCursor = Cursors.Hand;
|
||||
this.ZoomRectangleCursor = Cursors.SizeNWSE;
|
||||
this.ZoomHorizontalCursor = Cursors.SizeWE;
|
||||
this.ZoomVerticalCursor = Cursors.SizeNS;
|
||||
|
||||
var DoCopy = new DelegatePlotCommand<OxyKeyEventArgs>((view, controller, args) => this.DoCopy(view, args));
|
||||
this.ActualController.BindKeyDown(OxyKey.C, OxyModifierKeys.Control, DoCopy);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the actual model in the view.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The actual model.
|
||||
/// </value>
|
||||
Model IView.ActualModel
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Model;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the actual model.
|
||||
/// </summary>
|
||||
/// <value>The actual model.</value>
|
||||
public PlotModel ActualModel
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Model;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the actual controller.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The actual <see cref="IController" />.
|
||||
/// </value>
|
||||
IController IView.ActualController
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.ActualController;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the coordinates of the client area of the view.
|
||||
/// </summary>
|
||||
public OxyRect ClientArea
|
||||
{
|
||||
get
|
||||
{
|
||||
return new OxyRect(this.ClientRectangle.Left, this.ClientRectangle.Top, this.ClientRectangle.Width, this.ClientRectangle.Height);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the actual plot controller.
|
||||
/// </summary>
|
||||
/// <value>The actual plot controller.</value>
|
||||
public IPlotController ActualController
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Controller ?? (this.defaultController ?? (this.defaultController = new PlotController()));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the model.
|
||||
/// </summary>
|
||||
[Browsable(false)]
|
||||
[DefaultValue(null)]
|
||||
[Category(OxyPlotCategory)]
|
||||
public PlotModel Model
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.model;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (this.model != value)
|
||||
{
|
||||
this.model = value;
|
||||
this.OnModelChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the plot controller.
|
||||
/// </summary>
|
||||
/// <value>The controller.</value>
|
||||
[Browsable(false)]
|
||||
[DefaultValue(null)]
|
||||
[Category(OxyPlotCategory)]
|
||||
public IPlotController Controller { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pan cursor.
|
||||
/// </summary>
|
||||
[Category(OxyPlotCategory)]
|
||||
public Cursor PanCursor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the horizontal zoom cursor.
|
||||
/// </summary>
|
||||
[Category(OxyPlotCategory)]
|
||||
public Cursor ZoomHorizontalCursor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the rectangle zoom cursor.
|
||||
/// </summary>
|
||||
[Category(OxyPlotCategory)]
|
||||
public Cursor ZoomRectangleCursor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the vertical zoom cursor.
|
||||
/// </summary>
|
||||
[Category(OxyPlotCategory)]
|
||||
public Cursor ZoomVerticalCursor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Hides the tracker.
|
||||
/// </summary>
|
||||
public void HideTracker()
|
||||
{
|
||||
if (this.trackerLabel != null)
|
||||
{
|
||||
this.trackerLabel.Visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hides the zoom rectangle.
|
||||
/// </summary>
|
||||
public void HideZoomRectangle()
|
||||
{
|
||||
this.zoomRectangle = Rectangle.Empty;
|
||||
this.Invalidate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invalidates the plot (not blocking the UI thread)
|
||||
/// </summary>
|
||||
/// <param name="updateData">if set to <c>true</c>, all data collections will be updated.</param>
|
||||
public void InvalidatePlot(bool updateData)
|
||||
{
|
||||
lock (this.invalidateLock)
|
||||
{
|
||||
this.isModelInvalidated = true;
|
||||
this.updateDataFlag = this.updateDataFlag || updateData;
|
||||
}
|
||||
|
||||
this.Invalidate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the Model property has been changed.
|
||||
/// </summary>
|
||||
public void OnModelChanged()
|
||||
{
|
||||
lock (this.modelLock)
|
||||
{
|
||||
if (this.currentModel != null)
|
||||
{
|
||||
((IPlotModel)this.currentModel).AttachPlotView(null);
|
||||
this.currentModel = null;
|
||||
}
|
||||
|
||||
if (this.Model != null)
|
||||
{
|
||||
((IPlotModel)this.Model).AttachPlotView(this);
|
||||
this.currentModel = this.Model;
|
||||
}
|
||||
}
|
||||
|
||||
this.InvalidatePlot(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the cursor type.
|
||||
/// </summary>
|
||||
/// <param name="cursorType">The cursor type.</param>
|
||||
public void SetCursorType(CursorType cursorType)
|
||||
{
|
||||
switch (cursorType)
|
||||
{
|
||||
case CursorType.Pan:
|
||||
this.Cursor = this.PanCursor;
|
||||
break;
|
||||
case CursorType.ZoomRectangle:
|
||||
this.Cursor = this.ZoomRectangleCursor;
|
||||
break;
|
||||
case CursorType.ZoomHorizontal:
|
||||
this.Cursor = this.ZoomHorizontalCursor;
|
||||
break;
|
||||
case CursorType.ZoomVertical:
|
||||
this.Cursor = this.ZoomVerticalCursor;
|
||||
break;
|
||||
default:
|
||||
this.Cursor = Cursors.Arrow;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows the tracker.
|
||||
/// </summary>
|
||||
/// <param name="data">The data.</param>
|
||||
public void ShowTracker(TrackerHitResult data)
|
||||
{
|
||||
if (this.trackerLabel == null)
|
||||
{
|
||||
this.trackerLabel = new Label { Parent = this, BackColor = Color.LightSkyBlue, AutoSize = true, Padding = new Padding(5) };
|
||||
}
|
||||
|
||||
this.trackerLabel.Text = data.ToString();
|
||||
this.trackerLabel.Top = Math.Min(Math.Max(0, (int)data.Position.Y - this.trackerLabel.Height), this.Height - this.trackerLabel.Height);
|
||||
this.trackerLabel.Left = Math.Min(Math.Max(0, (int)data.Position.X - (this.trackerLabel.Width / 2)), this.Width - this.trackerLabel.Width);
|
||||
this.trackerLabel.Visible = true;
|
||||
this.trackerLabel.UseMnemonic = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows the zoom rectangle.
|
||||
/// </summary>
|
||||
/// <param name="rectangle">The rectangle.</param>
|
||||
public void ShowZoomRectangle(OxyRect rectangle)
|
||||
{
|
||||
this.zoomRectangle = new Rectangle((int)rectangle.Left, (int)rectangle.Top, (int)rectangle.Width, (int)rectangle.Height);
|
||||
this.Invalidate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the clipboard text.
|
||||
/// </summary>
|
||||
/// <param name="text">The text.</param>
|
||||
public void SetClipboardText(string text)
|
||||
{
|
||||
try
|
||||
{
|
||||
// todo: can't get the following solution to work
|
||||
// http://stackoverflow.com/questions/5707990/requested-clipboard-operation-did-not-succeed
|
||||
Clipboard.SetText(text);
|
||||
}
|
||||
catch (ExternalException ee)
|
||||
{
|
||||
// Requested Clipboard operation did not succeed.
|
||||
MessageBox.Show(this, ee.Message, "OxyPlot");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseDown" /> event.
|
||||
/// </summary>
|
||||
/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs" /> that contains the event data.</param>
|
||||
protected override void OnMouseDown(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseDown(e);
|
||||
|
||||
this.Focus();
|
||||
this.Capture = true;
|
||||
|
||||
this.ActualController.HandleMouseDown(this, e.ToMouseDownEventArgs(GetModifiers()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseMove" /> event.
|
||||
/// </summary>
|
||||
/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs" /> that contains the event data.</param>
|
||||
protected override void OnMouseMove(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseMove(e);
|
||||
|
||||
this.ActualController.HandleMouseMove(this, e.ToMouseEventArgs(GetModifiers()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseUp" /> event.
|
||||
/// </summary>
|
||||
/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs" /> that contains the event data.</param>
|
||||
protected override void OnMouseUp(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseUp(e);
|
||||
this.Capture = false;
|
||||
this.ActualController.HandleMouseUp(this, e.ToMouseUpEventArgs(GetModifiers()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseEnter" /> event.
|
||||
/// </summary>
|
||||
/// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
|
||||
protected override void OnMouseEnter(EventArgs e)
|
||||
{
|
||||
base.OnMouseEnter(e);
|
||||
this.ActualController.HandleMouseEnter(this, e.ToMouseEventArgs(GetModifiers()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseLeave" /> event.
|
||||
/// </summary>
|
||||
/// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
|
||||
protected override void OnMouseLeave(EventArgs e)
|
||||
{
|
||||
base.OnMouseLeave(e);
|
||||
this.ActualController.HandleMouseLeave(this, e.ToMouseEventArgs(GetModifiers()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseWheel" /> event.
|
||||
/// </summary>
|
||||
/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs" /> that contains the event data.</param>
|
||||
protected override void OnMouseWheel(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseWheel(e);
|
||||
this.ActualController.HandleMouseWheel(this, e.ToMouseWheelEventArgs(GetModifiers()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.Windows.Forms.Control.Paint" /> event.
|
||||
/// </summary>
|
||||
/// <param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs" /> that contains the event data.</param>
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
base.OnPaint(e);
|
||||
try
|
||||
{
|
||||
lock (this.invalidateLock)
|
||||
{
|
||||
if (this.isModelInvalidated)
|
||||
{
|
||||
if (this.model != null)
|
||||
{
|
||||
((IPlotModel)this.model).Update(this.updateDataFlag);
|
||||
this.updateDataFlag = false;
|
||||
}
|
||||
|
||||
this.isModelInvalidated = false;
|
||||
}
|
||||
}
|
||||
|
||||
lock (this.renderingLock)
|
||||
{
|
||||
this.renderContext.SetGraphicsTarget(e.Graphics);
|
||||
|
||||
if (this.model != null)
|
||||
{
|
||||
if (!this.model.Background.IsUndefined())
|
||||
{
|
||||
using (var brush = new SolidBrush(this.model.Background.ToColor()))
|
||||
{
|
||||
e.Graphics.FillRectangle(brush, e.ClipRectangle);
|
||||
}
|
||||
}
|
||||
|
||||
((IPlotModel)this.model).Render(this.renderContext, new OxyRect(0, 0, this.Width, this.Height));
|
||||
}
|
||||
|
||||
if (this.zoomRectangle != Rectangle.Empty)
|
||||
{
|
||||
using (var zoomBrush = new SolidBrush(Color.FromArgb(0x40, 0xFF, 0xFF, 0x00)))
|
||||
using (var zoomPen = new Pen(Color.Black))
|
||||
{
|
||||
zoomPen.DashPattern = new float[] { 3, 1 };
|
||||
e.Graphics.FillRectangle(zoomBrush, this.zoomRectangle);
|
||||
e.Graphics.DrawRectangle(zoomPen, this.zoomRectangle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception paintException)
|
||||
{
|
||||
var trace = new StackTrace(paintException);
|
||||
Debug.WriteLine(paintException);
|
||||
Debug.WriteLine(trace);
|
||||
using (var font = new Font("Arial", 10))
|
||||
{
|
||||
e.Graphics.ResetTransform();
|
||||
e.Graphics.DrawString(
|
||||
"OxyPlot paint exception: " + paintException.Message, font, Brushes.Red, this.Width * 0.5f, this.Height * 0.5f, new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.Windows.Forms.Control.PreviewKeyDown" /> event.
|
||||
/// </summary>
|
||||
/// <param name="e">A <see cref="T:System.Windows.Forms.PreviewKeyDownEventArgs" /> that contains the event data.</param>
|
||||
protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
|
||||
{
|
||||
base.OnPreviewKeyDown(e);
|
||||
|
||||
var args = new OxyKeyEventArgs { ModifierKeys = GetModifiers(), Key = e.KeyCode.Convert() };
|
||||
this.ActualController.HandleKeyDown(this, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.Windows.Forms.Control.Resize" /> event.
|
||||
/// </summary>
|
||||
/// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
|
||||
protected override void OnResize(EventArgs e)
|
||||
{
|
||||
base.OnResize(e);
|
||||
this.InvalidatePlot(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes the PlotView.
|
||||
/// </summary>
|
||||
/// <param name="disposing">Whether to dispose managed resources or not.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
bool disposed = this.IsDisposed;
|
||||
|
||||
base.Dispose(disposing);
|
||||
|
||||
if (disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
this.renderContext.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current modifier keys.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="OxyModifierKeys" /> value.</returns>
|
||||
private static OxyModifierKeys GetModifiers()
|
||||
{
|
||||
var modifiers = OxyModifierKeys.None;
|
||||
|
||||
// ReSharper disable once RedundantNameQualifier
|
||||
if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
|
||||
{
|
||||
modifiers |= OxyModifierKeys.Shift;
|
||||
}
|
||||
|
||||
// ReSharper disable once RedundantNameQualifier
|
||||
if ((Control.ModifierKeys & Keys.Control) == Keys.Control)
|
||||
{
|
||||
modifiers |= OxyModifierKeys.Control;
|
||||
}
|
||||
|
||||
// ReSharper disable once RedundantNameQualifier
|
||||
if ((Control.ModifierKeys & Keys.Alt) == Keys.Alt)
|
||||
{
|
||||
modifiers |= OxyModifierKeys.Alt;
|
||||
}
|
||||
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the copy operation.
|
||||
/// </summary>
|
||||
private void DoCopy(IPlotView view, OxyInputEventArgs args)
|
||||
{
|
||||
var exporter = new PngExporter
|
||||
{
|
||||
Width = this.ClientRectangle.Width,
|
||||
Height = this.ClientRectangle.Height,
|
||||
};
|
||||
|
||||
var bitmap = exporter.ExportToBitmap(this.ActualModel);
|
||||
Clipboard.SetImage(bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
109
Source/OxyPlot.WindowsForms/PngExporter.cs
Normal file
109
Source/OxyPlot.WindowsForms/PngExporter.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="PngExporter.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Provides functionality to export plots to png.
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#if OXYPLOT_COREDRAWING
|
||||
namespace OxyPlot.Core.Drawing
|
||||
#else
|
||||
namespace OxyPlot.WindowsForms
|
||||
#endif
|
||||
{
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
|
||||
/// <summary>
|
||||
/// Provides functionality to export plots to png.
|
||||
/// </summary>
|
||||
public class PngExporter : IExporter
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PngExporter" /> class.
|
||||
/// </summary>
|
||||
public PngExporter()
|
||||
{
|
||||
this.Width = 700;
|
||||
this.Height = 400;
|
||||
this.Resolution = 96;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the width of the output image.
|
||||
/// </summary>
|
||||
public int Width { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the height of the output image.
|
||||
/// </summary>
|
||||
public int Height { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the resolution (dpi) of the output image.
|
||||
/// </summary>
|
||||
public double Resolution { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Exports the specified model.
|
||||
/// </summary>
|
||||
/// <param name="model">The model.</param>
|
||||
/// <param name="fileName">The file name.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <param name="resolution">The resolution.</param>
|
||||
public static void Export(IPlotModel model, string fileName, int width, int height, double resolution = 96)
|
||||
{
|
||||
var exporter = new PngExporter { Width = width, Height = height, Resolution = resolution };
|
||||
using (var stream = File.Create(fileName))
|
||||
{
|
||||
exporter.Export(model, stream);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exports the specified <see cref="PlotModel" /> to the specified <see cref="Stream" />.
|
||||
/// </summary>
|
||||
/// <param name="model">The model.</param>
|
||||
/// <param name="stream">The output stream.</param>
|
||||
public void Export(IPlotModel model, Stream stream)
|
||||
{
|
||||
using (var bm = this.ExportToBitmap(model))
|
||||
{
|
||||
bm.Save(stream, ImageFormat.Png);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exports the specified <see cref="PlotModel" /> to a <see cref="Bitmap" />.
|
||||
/// </summary>
|
||||
/// <param name="model">The model to export.</param>
|
||||
/// <returns>A bitmap.</returns>
|
||||
public Bitmap ExportToBitmap(IPlotModel model)
|
||||
{
|
||||
var bm = new Bitmap(this.Width, this.Height);
|
||||
using (var g = Graphics.FromImage(bm))
|
||||
{
|
||||
if (model.Background.IsVisible())
|
||||
{
|
||||
using (var brush = model.Background.ToBrush())
|
||||
{
|
||||
g.FillRectangle(brush, 0, 0, this.Width, this.Height);
|
||||
}
|
||||
}
|
||||
|
||||
using (var rc = new GraphicsRenderContext(g) { RendersToScreen = false })
|
||||
{
|
||||
model.Update(true);
|
||||
model.Render(rc, new OxyRect(0, 0, this.Width, this.Height));
|
||||
}
|
||||
|
||||
bm.SetResolution((float)this.Resolution, (float)this.Resolution);
|
||||
return bm;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
9
Source/OxyPlot.WindowsForms/Properties/AssemblyInfo.cs
Normal file
9
Source/OxyPlot.WindowsForms/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="AssemblyDescription.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
|
||||
[assembly: CLSCompliant(false)]
|
||||
48
Source/OxyPlot.WindowsForms/SvgExporter.cs
Normal file
48
Source/OxyPlot.WindowsForms/SvgExporter.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="SvgExporter.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Provides functionality to export plots to scalable vector graphics using <see cref="Graphics" /> for text measuring.
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace OxyPlot.WindowsForms
|
||||
{
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
/// <summary>
|
||||
/// Provides functionality to export plots to scalable vector graphics using <see cref="Graphics" /> for text measuring.
|
||||
/// </summary>
|
||||
public class SvgExporter : OxyPlot.SvgExporter, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// The graphics drawing surface.
|
||||
/// </summary>
|
||||
private Graphics g;
|
||||
|
||||
/// <summary>
|
||||
/// The render context.
|
||||
/// </summary>
|
||||
private GraphicsRenderContext grc;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SvgExporter" /> class.
|
||||
/// </summary>
|
||||
public SvgExporter()
|
||||
{
|
||||
this.g = Graphics.FromHwnd(IntPtr.Zero);
|
||||
this.TextMeasurer = this.grc = new GraphicsRenderContext(this.g);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
this.g.Dispose();
|
||||
this.grc.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
291
Source/OxyPlot.WindowsForms/WindowsFormsConverterExtensions.cs
Normal file
291
Source/OxyPlot.WindowsForms/WindowsFormsConverterExtensions.cs
Normal file
@@ -0,0 +1,291 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="WindowsFormsConverterExtensions.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Extension method used to convert to/from Windows/Windows.Media classes.
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace OxyPlot.WindowsForms
|
||||
{
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
/// <summary>
|
||||
/// Extension method used to convert to/from WindowsForms classes.
|
||||
/// </summary>
|
||||
public static class WindowsFormsConverterExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a <see cref="MouseButtons" /> to a <see cref="OxyMouseButton" />.
|
||||
/// </summary>
|
||||
/// <param name="button">The button to convert.</param>
|
||||
/// <returns>The converted mouse button.</returns>
|
||||
public static OxyMouseButton Convert(this MouseButtons button)
|
||||
{
|
||||
switch (button)
|
||||
{
|
||||
case MouseButtons.Left:
|
||||
return OxyMouseButton.Left;
|
||||
case MouseButtons.Middle:
|
||||
return OxyMouseButton.Middle;
|
||||
case MouseButtons.Right:
|
||||
return OxyMouseButton.Right;
|
||||
case MouseButtons.XButton1:
|
||||
return OxyMouseButton.XButton1;
|
||||
case MouseButtons.XButton2:
|
||||
return OxyMouseButton.XButton2;
|
||||
}
|
||||
|
||||
return OxyMouseButton.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts <see cref="MouseEventArgs" /> to <see cref="OxyMouseWheelEventArgs" /> for a mouse wheel event.
|
||||
/// </summary>
|
||||
/// <param name="e">The <see cref="MouseEventArgs" /> instance containing the event data.</param>
|
||||
/// <param name="modifiers">The modifiers.</param>
|
||||
/// <returns>A <see cref="OxyMouseWheelEventArgs" /> containing the converted event arguments.</returns>
|
||||
public static OxyMouseWheelEventArgs ToMouseWheelEventArgs(this MouseEventArgs e, OxyModifierKeys modifiers)
|
||||
{
|
||||
return new OxyMouseWheelEventArgs
|
||||
{
|
||||
Position = e.Location.ToScreenPoint(),
|
||||
ModifierKeys = modifiers,
|
||||
Delta = e.Delta
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts <see cref="MouseEventArgs" /> to <see cref="OxyMouseEventArgs" /> for a mouse down event.
|
||||
/// </summary>
|
||||
/// <param name="e">The <see cref="MouseEventArgs" /> instance containing the event data.</param>
|
||||
/// <param name="modifiers">The modifiers.</param>
|
||||
/// <returns>A <see cref="OxyMouseDownEventArgs" /> containing the converted event arguments.</returns>
|
||||
public static OxyMouseDownEventArgs ToMouseDownEventArgs(this MouseEventArgs e, OxyModifierKeys modifiers)
|
||||
{
|
||||
return new OxyMouseDownEventArgs
|
||||
{
|
||||
ChangedButton = e.Button.Convert(),
|
||||
ClickCount = e.Clicks,
|
||||
Position = e.Location.ToScreenPoint(),
|
||||
ModifierKeys = modifiers
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts <see cref="MouseEventArgs" /> to <see cref="OxyMouseEventArgs" /> for a mouse up event.
|
||||
/// </summary>
|
||||
/// <param name="e">The <see cref="MouseEventArgs" /> instance containing the event data.</param>
|
||||
/// <param name="modifiers">The modifiers.</param>
|
||||
/// <returns>A <see cref="OxyMouseEventArgs" /> containing the converted event arguments.</returns>
|
||||
public static OxyMouseEventArgs ToMouseUpEventArgs(this MouseEventArgs e, OxyModifierKeys modifiers)
|
||||
{
|
||||
return new OxyMouseEventArgs
|
||||
{
|
||||
Position = e.Location.ToScreenPoint(),
|
||||
ModifierKeys = modifiers
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts <see cref="MouseEventArgs" /> to <see cref="OxyMouseEventArgs" /> for a mouse event.
|
||||
/// </summary>
|
||||
/// <param name="e">The <see cref="MouseEventArgs" /> instance containing the event data.</param>
|
||||
/// <param name="modifiers">The modifiers.</param>
|
||||
/// <returns>A <see cref="OxyMouseEventArgs" /> containing the converted event arguments.</returns>
|
||||
public static OxyMouseEventArgs ToMouseEventArgs(this MouseEventArgs e, OxyModifierKeys modifiers)
|
||||
{
|
||||
return new OxyMouseEventArgs
|
||||
{
|
||||
Position = e.Location.ToScreenPoint(),
|
||||
ModifierKeys = modifiers
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts <see cref="MouseEventArgs" /> to <see cref="OxyMouseEventArgs" /> for a mouse event.
|
||||
/// </summary>
|
||||
/// <param name="e">The <see cref="MouseEventArgs" /> instance containing the event data.</param>
|
||||
/// <param name="modifiers">The modifiers.</param>
|
||||
/// <returns>A <see cref="OxyMouseEventArgs" /> containing the converted event arguments.</returns>
|
||||
public static OxyMouseEventArgs ToMouseEventArgs(this EventArgs e, OxyModifierKeys modifiers)
|
||||
{
|
||||
return new OxyMouseEventArgs
|
||||
{
|
||||
ModifierKeys = modifiers
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the specified key.
|
||||
/// </summary>
|
||||
/// <param name="k">The key to convert.</param>
|
||||
/// <returns>The converted key.</returns>
|
||||
public static OxyKey Convert(this Keys k)
|
||||
{
|
||||
switch (k)
|
||||
{
|
||||
case Keys.A:
|
||||
return OxyKey.A;
|
||||
case Keys.Add:
|
||||
return OxyKey.Add;
|
||||
case Keys.B:
|
||||
return OxyKey.B;
|
||||
case Keys.Back:
|
||||
return OxyKey.Backspace;
|
||||
case Keys.C:
|
||||
return OxyKey.C;
|
||||
case Keys.D:
|
||||
return OxyKey.D;
|
||||
case Keys.D0:
|
||||
return OxyKey.D0;
|
||||
case Keys.D1:
|
||||
return OxyKey.D1;
|
||||
case Keys.D2:
|
||||
return OxyKey.D2;
|
||||
case Keys.D3:
|
||||
return OxyKey.D3;
|
||||
case Keys.D4:
|
||||
return OxyKey.D4;
|
||||
case Keys.D5:
|
||||
return OxyKey.D5;
|
||||
case Keys.D6:
|
||||
return OxyKey.D6;
|
||||
case Keys.D7:
|
||||
return OxyKey.D7;
|
||||
case Keys.D8:
|
||||
return OxyKey.D8;
|
||||
case Keys.D9:
|
||||
return OxyKey.D9;
|
||||
case Keys.Decimal:
|
||||
return OxyKey.Decimal;
|
||||
case Keys.Delete:
|
||||
return OxyKey.Delete;
|
||||
case Keys.Divide:
|
||||
return OxyKey.Divide;
|
||||
case Keys.Down:
|
||||
return OxyKey.Down;
|
||||
case Keys.E:
|
||||
return OxyKey.E;
|
||||
case Keys.End:
|
||||
return OxyKey.End;
|
||||
case Keys.Enter:
|
||||
return OxyKey.Enter;
|
||||
case Keys.Escape:
|
||||
return OxyKey.Escape;
|
||||
case Keys.F:
|
||||
return OxyKey.F;
|
||||
case Keys.F1:
|
||||
return OxyKey.F1;
|
||||
case Keys.F10:
|
||||
return OxyKey.F10;
|
||||
case Keys.F11:
|
||||
return OxyKey.F11;
|
||||
case Keys.F12:
|
||||
return OxyKey.F12;
|
||||
case Keys.F2:
|
||||
return OxyKey.F2;
|
||||
case Keys.F3:
|
||||
return OxyKey.F3;
|
||||
case Keys.F4:
|
||||
return OxyKey.F4;
|
||||
case Keys.F5:
|
||||
return OxyKey.F5;
|
||||
case Keys.F6:
|
||||
return OxyKey.F6;
|
||||
case Keys.F7:
|
||||
return OxyKey.F7;
|
||||
case Keys.F8:
|
||||
return OxyKey.F8;
|
||||
case Keys.F9:
|
||||
return OxyKey.F9;
|
||||
case Keys.G:
|
||||
return OxyKey.G;
|
||||
case Keys.H:
|
||||
return OxyKey.H;
|
||||
case Keys.Home:
|
||||
return OxyKey.Home;
|
||||
case Keys.I:
|
||||
return OxyKey.I;
|
||||
case Keys.Insert:
|
||||
return OxyKey.Insert;
|
||||
case Keys.J:
|
||||
return OxyKey.J;
|
||||
case Keys.K:
|
||||
return OxyKey.K;
|
||||
case Keys.L:
|
||||
return OxyKey.L;
|
||||
case Keys.Left:
|
||||
return OxyKey.Left;
|
||||
case Keys.M:
|
||||
return OxyKey.M;
|
||||
case Keys.Multiply:
|
||||
return OxyKey.Multiply;
|
||||
case Keys.N:
|
||||
return OxyKey.N;
|
||||
case Keys.NumPad0:
|
||||
return OxyKey.NumPad0;
|
||||
case Keys.NumPad1:
|
||||
return OxyKey.NumPad1;
|
||||
case Keys.NumPad2:
|
||||
return OxyKey.NumPad2;
|
||||
case Keys.NumPad3:
|
||||
return OxyKey.NumPad3;
|
||||
case Keys.NumPad4:
|
||||
return OxyKey.NumPad4;
|
||||
case Keys.NumPad5:
|
||||
return OxyKey.NumPad5;
|
||||
case Keys.NumPad6:
|
||||
return OxyKey.NumPad6;
|
||||
case Keys.NumPad7:
|
||||
return OxyKey.NumPad7;
|
||||
case Keys.NumPad8:
|
||||
return OxyKey.NumPad8;
|
||||
case Keys.NumPad9:
|
||||
return OxyKey.NumPad9;
|
||||
case Keys.O:
|
||||
return OxyKey.O;
|
||||
case Keys.P:
|
||||
return OxyKey.P;
|
||||
case Keys.PageDown:
|
||||
return OxyKey.PageDown;
|
||||
case Keys.PageUp:
|
||||
return OxyKey.PageUp;
|
||||
case Keys.Q:
|
||||
return OxyKey.Q;
|
||||
case Keys.R:
|
||||
return OxyKey.R;
|
||||
case Keys.Right:
|
||||
return OxyKey.Right;
|
||||
case Keys.S:
|
||||
return OxyKey.S;
|
||||
case Keys.Space:
|
||||
return OxyKey.Space;
|
||||
case Keys.Subtract:
|
||||
return OxyKey.Subtract;
|
||||
case Keys.T:
|
||||
return OxyKey.T;
|
||||
case Keys.Tab:
|
||||
return OxyKey.Tab;
|
||||
case Keys.U:
|
||||
return OxyKey.U;
|
||||
case Keys.Up:
|
||||
return OxyKey.Up;
|
||||
case Keys.V:
|
||||
return OxyKey.V;
|
||||
case Keys.W:
|
||||
return OxyKey.W;
|
||||
case Keys.X:
|
||||
return OxyKey.X;
|
||||
case Keys.Y:
|
||||
return OxyKey.Y;
|
||||
case Keys.Z:
|
||||
return OxyKey.Z;
|
||||
default:
|
||||
return OxyKey.Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user