Neuerstellung

- Quelle: https://github.com/oxyplot/oxyplot
This commit is contained in:
2023-09-02 09:24:59 +02:00
commit 9520c1fa4a
810 changed files with 117869 additions and 0 deletions

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

View 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);
}
}
}
}

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

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

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

View File

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

Binary file not shown.

View 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);
}
}
}
}
}

View 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);
}
}
}

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

View File

@@ -0,0 +1,9 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="AssemblyDescription.cs" company="OxyPlot">
// Copyright (c) 2014 OxyPlot contributors
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using System;
[assembly: CLSCompliant(false)]

View 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();
}
}
}

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