mirror of
https://github.com/openhardwaremonitor/openhardwaremonitor
synced 2025-09-05 08:45:38 +00:00
896 lines
28 KiB
C#
896 lines
28 KiB
C#
// --------------------------------------------------------------------------------------------------------------------
|
|
// <copyright file="Plot.cs" company="OxyPlot">
|
|
// The MIT License (MIT)
|
|
//
|
|
// Copyright (c) 2012 Oystein Bjorke
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
// permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
// </copyright>
|
|
// <summary>
|
|
// Represents a control that displays a plot.
|
|
// </summary>
|
|
// --------------------------------------------------------------------------------------------------------------------
|
|
namespace OxyPlot.WindowsForms
|
|
{
|
|
using System;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
using System.Drawing;
|
|
using System.Runtime.InteropServices;
|
|
using System.Windows.Forms;
|
|
|
|
using OxyPlot.Axes;
|
|
using OxyPlot.Series;
|
|
|
|
/// <summary>
|
|
/// Represents a control that displays a plot.
|
|
/// </summary>
|
|
[Serializable]
|
|
public class Plot : Control, IPlotControl
|
|
{
|
|
/// <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 current model (holding a reference to this plot control).
|
|
/// </summary>
|
|
[NonSerialized]
|
|
private PlotModel currentModel;
|
|
|
|
/// <summary>
|
|
/// The is model invalidated.
|
|
/// </summary>
|
|
private bool isModelInvalidated;
|
|
|
|
/// <summary>
|
|
/// The model.
|
|
/// </summary>
|
|
private PlotModel model;
|
|
|
|
/// <summary>
|
|
/// The mouse manipulator.
|
|
/// </summary>
|
|
[NonSerialized]
|
|
private ManipulatorBase mouseManipulator;
|
|
|
|
/// <summary>
|
|
/// The update data flag.
|
|
/// </summary>
|
|
private bool updateDataFlag = true;
|
|
|
|
/// <summary>
|
|
/// The zoom rectangle.
|
|
/// </summary>
|
|
private Rectangle zoomRectangle;
|
|
|
|
/// <summary>
|
|
/// The render context.
|
|
/// </summary>
|
|
private GraphicsRenderContext renderContext;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="Plot"/> class.
|
|
/// </summary>
|
|
public Plot()
|
|
{
|
|
this.renderContext = new GraphicsRenderContext();
|
|
|
|
// ReSharper disable DoNotCallOverridableMethodsInConstructor
|
|
this.DoubleBuffered = true;
|
|
// ReSharper restore DoNotCallOverridableMethodsInConstructor
|
|
this.KeyboardPanHorizontalStep = 0.1;
|
|
this.KeyboardPanVerticalStep = 0.1;
|
|
this.PanCursor = Cursors.Hand;
|
|
this.ZoomRectangleCursor = Cursors.SizeNWSE;
|
|
this.ZoomHorizontalCursor = Cursors.SizeWE;
|
|
this.ZoomVerticalCursor = Cursors.SizeNS;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the actual model.
|
|
/// </summary>
|
|
/// <value> The actual model. </value>
|
|
public PlotModel ActualModel
|
|
{
|
|
get
|
|
{
|
|
return this.Model;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the keyboard pan horizontal step.
|
|
/// </summary>
|
|
/// <value> The keyboard pan horizontal step. </value>
|
|
[Category(OxyPlotCategory)]
|
|
public double KeyboardPanHorizontalStep { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the keyboard pan vertical step.
|
|
/// </summary>
|
|
/// <value> The keyboard pan vertical step. </value>
|
|
[Category(OxyPlotCategory)]
|
|
public double KeyboardPanVerticalStep { get; set; }
|
|
|
|
/// <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 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 vertical zoom cursor.
|
|
/// </summary>
|
|
[Category(OxyPlotCategory)]
|
|
public Cursor ZoomVerticalCursor { get; set; }
|
|
|
|
/// <summary>
|
|
/// Get the axes from a point.
|
|
/// </summary>
|
|
/// <param name="pt">
|
|
/// The point.
|
|
/// </param>
|
|
/// <param name="xaxis">
|
|
/// The x axis.
|
|
/// </param>
|
|
/// <param name="yaxis">
|
|
/// The y axis.
|
|
/// </param>
|
|
public void GetAxesFromPoint(ScreenPoint pt, out Axis xaxis, out Axis yaxis)
|
|
{
|
|
if (this.Model == null)
|
|
{
|
|
xaxis = null;
|
|
yaxis = null;
|
|
return;
|
|
}
|
|
|
|
this.Model.GetAxesFromPoint(pt, out xaxis, out yaxis);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the series from a point.
|
|
/// </summary>
|
|
/// <param name="pt">
|
|
/// The point (screen coordinates).
|
|
/// </param>
|
|
/// <param name="limit">
|
|
/// The limit.
|
|
/// </param>
|
|
/// <returns>
|
|
/// The series.
|
|
/// </returns>
|
|
public Series GetSeriesFromPoint(ScreenPoint pt, double limit)
|
|
{
|
|
if (this.Model == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return this.Model.GetSeriesFromPoint(pt, limit);
|
|
}
|
|
|
|
/// <summary>
|
|
/// The hide tracker.
|
|
/// </summary>
|
|
public void HideTracker()
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// The hide zoom rectangle.
|
|
/// </summary>
|
|
public void HideZoomRectangle()
|
|
{
|
|
this.zoomRectangle = Rectangle.Empty;
|
|
this.Invalidate();
|
|
}
|
|
|
|
/// <summary>
|
|
/// The invalidate plot.
|
|
/// </summary>
|
|
/// <param name="updateData">
|
|
/// The update data.
|
|
/// </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)
|
|
{
|
|
this.currentModel.AttachPlotControl(null);
|
|
}
|
|
|
|
if (this.Model != null)
|
|
{
|
|
if (this.Model.PlotControl != null)
|
|
{
|
|
throw new InvalidOperationException(
|
|
"This PlotModel is already in use by some other plot control.");
|
|
}
|
|
|
|
this.Model.AttachPlotControl(this);
|
|
this.currentModel = this.Model;
|
|
}
|
|
}
|
|
|
|
this.InvalidatePlot(true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// The pan.
|
|
/// </summary>
|
|
/// <param name="axis">
|
|
/// The axis.
|
|
/// </param>
|
|
/// <param name="x0">
|
|
/// The x 0.
|
|
/// </param>
|
|
/// <param name="x1">
|
|
/// The x 1.
|
|
/// </param>
|
|
public void Pan(Axis axis, ScreenPoint x0, ScreenPoint x1)
|
|
{
|
|
axis.Pan(x0, x1);
|
|
this.InvalidatePlot(false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Pans all axes.
|
|
/// </summary>
|
|
/// <param name="deltax">
|
|
/// The horizontal delta.
|
|
/// </param>
|
|
/// <param name="deltay">
|
|
/// The vertical delta.
|
|
/// </param>
|
|
public void PanAll(double deltax, double deltay)
|
|
{
|
|
foreach (var a in this.ActualModel.Axes)
|
|
{
|
|
a.Pan(a.IsHorizontal() ? deltax : deltay);
|
|
}
|
|
|
|
this.InvalidatePlot(false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// The refresh plot.
|
|
/// </summary>
|
|
/// <param name="updateData">
|
|
/// The update data.
|
|
/// </param>
|
|
public void RefreshPlot(bool updateData)
|
|
{
|
|
lock (this.invalidateLock)
|
|
{
|
|
this.isModelInvalidated = true;
|
|
this.updateDataFlag = this.updateDataFlag || updateData;
|
|
}
|
|
|
|
this.Refresh();
|
|
}
|
|
|
|
/// <summary>
|
|
/// The reset.
|
|
/// </summary>
|
|
/// <param name="axis">
|
|
/// The axis.
|
|
/// </param>
|
|
public void Reset(Axis axis)
|
|
{
|
|
axis.Reset();
|
|
this.InvalidatePlot(false);
|
|
}
|
|
|
|
/// <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>
|
|
/// The show tracker.
|
|
/// </summary>
|
|
/// <param name="data">
|
|
/// The data.
|
|
/// </param>
|
|
public void ShowTracker(TrackerHitResult data)
|
|
{
|
|
// not implemented for WindowsForms
|
|
}
|
|
|
|
/// <summary>
|
|
/// The show zoom rectangle.
|
|
/// </summary>
|
|
/// <param name="r">
|
|
/// The r.
|
|
/// </param>
|
|
public void ShowZoomRectangle(OxyRect r)
|
|
{
|
|
this.zoomRectangle = new Rectangle((int)r.Left, (int)r.Top, (int)r.Width, (int)r.Height);
|
|
this.Invalidate();
|
|
}
|
|
|
|
/// <summary>
|
|
/// The zoom.
|
|
/// </summary>
|
|
/// <param name="axis">
|
|
/// The axis.
|
|
/// </param>
|
|
/// <param name="p1">
|
|
/// The p 1.
|
|
/// </param>
|
|
/// <param name="p2">
|
|
/// The p 2.
|
|
/// </param>
|
|
public void Zoom(Axis axis, double p1, double p2)
|
|
{
|
|
axis.Zoom(p1, p2);
|
|
this.InvalidatePlot(false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// The zoom all.
|
|
/// </summary>
|
|
public void ZoomAll()
|
|
{
|
|
foreach (var a in this.Model.Axes)
|
|
{
|
|
a.Reset();
|
|
}
|
|
|
|
this.InvalidatePlot(false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Zooms all axes.
|
|
/// </summary>
|
|
/// <param name="delta">
|
|
/// The delta.
|
|
/// </param>
|
|
public void ZoomAllAxes(double delta)
|
|
{
|
|
foreach (var a in this.ActualModel.Axes)
|
|
{
|
|
this.ZoomAt(a, delta);
|
|
}
|
|
|
|
this.RefreshPlot(false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// The zoom at.
|
|
/// </summary>
|
|
/// <param name="axis">
|
|
/// The axis.
|
|
/// </param>
|
|
/// <param name="factor">
|
|
/// The factor.
|
|
/// </param>
|
|
/// <param name="x">
|
|
/// The x.
|
|
/// </param>
|
|
public void ZoomAt(Axis axis, double factor, double x = double.NaN)
|
|
{
|
|
if (double.IsNaN(x))
|
|
{
|
|
double sx = (axis.Transform(axis.ActualMaximum) + axis.Transform(axis.ActualMinimum)) * 0.5;
|
|
x = axis.InverseTransform(sx);
|
|
}
|
|
|
|
axis.ZoomAt(factor, x);
|
|
this.InvalidatePlot(false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// The on mouse down.
|
|
/// </summary>
|
|
/// <param name="e">
|
|
/// The e.
|
|
/// </param>
|
|
protected override void OnMouseDown(MouseEventArgs e)
|
|
{
|
|
base.OnMouseDown(e);
|
|
|
|
if (this.mouseManipulator != null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
this.Focus();
|
|
this.Capture = true;
|
|
|
|
if (this.ActualModel != null)
|
|
{
|
|
var args = this.CreateMouseEventArgs(e);
|
|
this.ActualModel.HandleMouseDown(this, args);
|
|
if (args.Handled)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
this.mouseManipulator = this.GetManipulator(e);
|
|
|
|
if (this.mouseManipulator != null)
|
|
{
|
|
this.mouseManipulator.Started(this.CreateManipulationEventArgs(e));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The on mouse move.
|
|
/// </summary>
|
|
/// <param name="e">
|
|
/// The e.
|
|
/// </param>
|
|
protected override void OnMouseMove(MouseEventArgs e)
|
|
{
|
|
base.OnMouseMove(e);
|
|
|
|
if (this.ActualModel != null)
|
|
{
|
|
var args = this.CreateMouseEventArgs(e);
|
|
this.ActualModel.HandleMouseMove(this, args);
|
|
if (args.Handled)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (this.mouseManipulator != null)
|
|
{
|
|
this.mouseManipulator.Delta(this.CreateManipulationEventArgs(e));
|
|
}
|
|
}
|
|
|
|
/// <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;
|
|
|
|
if (this.ActualModel != null)
|
|
{
|
|
var args = this.CreateMouseEventArgs(e);
|
|
this.ActualModel.HandleMouseUp(this, args);
|
|
if (args.Handled)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (this.mouseManipulator != null)
|
|
{
|
|
this.mouseManipulator.Completed(this.CreateManipulationEventArgs(e));
|
|
}
|
|
|
|
this.mouseManipulator = null;
|
|
}
|
|
|
|
/// <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);
|
|
bool isControlDown = ModifierKeys == Keys.Control;
|
|
var m = new ZoomStepManipulator(this, e.Delta * 0.001, isControlDown);
|
|
m.Started(new ManipulationEventArgs(e.Location.ToScreenPoint()));
|
|
}
|
|
|
|
/// <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)
|
|
{
|
|
this.model.Update(this.updateDataFlag);
|
|
this.updateDataFlag = false;
|
|
}
|
|
|
|
this.isModelInvalidated = false;
|
|
}
|
|
}
|
|
|
|
lock (this.renderingLock)
|
|
{
|
|
this.renderContext.SetGraphicsTarget(e.Graphics);
|
|
if (this.model != null)
|
|
{
|
|
this.model.Render(this.renderContext, 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.DrawString(
|
|
"OxyPlot paint exception: " + paintException.Message, font, Brushes.Red, 10, 10);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <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);
|
|
if (e.KeyCode == Keys.A)
|
|
{
|
|
this.ZoomAll();
|
|
}
|
|
|
|
bool control = (e.Modifiers & Keys.Control) == Keys.Control;
|
|
bool alt = (e.Modifiers & Keys.Alt) == Keys.Alt;
|
|
|
|
double deltax = 0;
|
|
double deltay = 0;
|
|
double zoom = 0;
|
|
switch (e.KeyCode)
|
|
{
|
|
case Keys.Up:
|
|
deltay = -1;
|
|
break;
|
|
case Keys.Down:
|
|
deltay = 1;
|
|
break;
|
|
case Keys.Left:
|
|
deltax = -1;
|
|
break;
|
|
case Keys.Right:
|
|
deltax = 1;
|
|
break;
|
|
case Keys.Add:
|
|
case Keys.Oemplus:
|
|
case Keys.PageUp:
|
|
zoom = 1;
|
|
break;
|
|
case Keys.Subtract:
|
|
case Keys.OemMinus:
|
|
case Keys.PageDown:
|
|
zoom = -1;
|
|
break;
|
|
}
|
|
|
|
if ((deltax * deltax) + (deltay * deltay) > 0)
|
|
{
|
|
deltax = deltax * this.ActualModel.PlotArea.Width * this.KeyboardPanHorizontalStep;
|
|
deltay = deltay * this.ActualModel.PlotArea.Height * this.KeyboardPanVerticalStep;
|
|
|
|
// small steps if the user is pressing control
|
|
if (control)
|
|
{
|
|
deltax *= 0.2;
|
|
deltay *= 0.2;
|
|
}
|
|
|
|
this.PanAll(deltax, deltay);
|
|
|
|
// e.Handled = true;
|
|
}
|
|
|
|
if (Math.Abs(zoom) > 1e-8)
|
|
{
|
|
if (control)
|
|
{
|
|
zoom *= 0.2;
|
|
}
|
|
|
|
this.ZoomAllAxes(1 + (zoom * 0.12));
|
|
|
|
// e.Handled = true;
|
|
}
|
|
|
|
if (control && alt && this.ActualModel != null)
|
|
{
|
|
switch (e.KeyCode)
|
|
{
|
|
case Keys.R:
|
|
this.SetClipboardText(this.ActualModel.CreateTextReport());
|
|
break;
|
|
case Keys.C:
|
|
this.SetClipboardText(this.ActualModel.ToCode());
|
|
break;
|
|
case Keys.X:
|
|
|
|
// this.SetClipboardText(this.ActualModel.ToXml());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <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>
|
|
/// Converts the changed button.
|
|
/// </summary>
|
|
/// <param name="e">
|
|
/// The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.
|
|
/// </param>
|
|
/// <returns>
|
|
/// The mouse button.
|
|
/// </returns>
|
|
private static OxyMouseButton ConvertChangedButton(MouseEventArgs e)
|
|
{
|
|
switch (e.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.Left;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates the mouse event arguments.
|
|
/// </summary>
|
|
/// <param name="e">
|
|
/// The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.
|
|
/// </param>
|
|
/// <returns>
|
|
/// Mouse event arguments.
|
|
/// </returns>
|
|
private OxyMouseEventArgs CreateMouseEventArgs(MouseEventArgs e)
|
|
{
|
|
return new OxyMouseEventArgs
|
|
{
|
|
ChangedButton = ConvertChangedButton(e),
|
|
Position = new ScreenPoint(e.Location.X, e.Location.Y),
|
|
IsShiftDown = (ModifierKeys & Keys.Shift) == Keys.Shift,
|
|
IsControlDown = (ModifierKeys & Keys.Control) == Keys.Control,
|
|
IsAltDown = (ModifierKeys & Keys.Alt) == Keys.Alt,
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates the manipulation event args.
|
|
/// </summary>
|
|
/// <param name="e">
|
|
/// The MouseEventArgs instance containing the event data.
|
|
/// </param>
|
|
/// <returns>
|
|
/// A manipulation event args object.
|
|
/// </returns>
|
|
private ManipulationEventArgs CreateManipulationEventArgs(MouseEventArgs e)
|
|
{
|
|
return new ManipulationEventArgs(e.Location.ToScreenPoint());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the manipulator for the current mouse button and modifier keys.
|
|
/// </summary>
|
|
/// <param name="e">
|
|
/// The event args.
|
|
/// </param>
|
|
/// <returns>
|
|
/// A manipulator or null if no gesture was recognized.
|
|
/// </returns>
|
|
private ManipulatorBase GetManipulator(MouseEventArgs e)
|
|
{
|
|
bool control = (ModifierKeys & Keys.Control) == Keys.Control;
|
|
bool shift = (ModifierKeys & Keys.Shift) == Keys.Shift;
|
|
bool alt = (ModifierKeys & Keys.Alt) == Keys.Alt;
|
|
|
|
bool lmb = e.Button == MouseButtons.Left;
|
|
bool rmb = e.Button == MouseButtons.Right;
|
|
bool mmb = e.Button == MouseButtons.Middle;
|
|
bool xb1 = e.Button == MouseButtons.XButton1;
|
|
bool xb2 = e.Button == MouseButtons.XButton2;
|
|
|
|
// MMB / control RMB / control+alt LMB
|
|
if (mmb || (control && lmb) || (control && alt && rmb))
|
|
{
|
|
return new ZoomRectangleManipulator(this);
|
|
}
|
|
|
|
// Right mouse button / alt+left mouse button
|
|
if (lmb || (rmb && alt))
|
|
{
|
|
if (e.Clicks == 2)
|
|
{
|
|
return new ResetManipulator(this);
|
|
}
|
|
return new PanManipulator(this);
|
|
}
|
|
|
|
// Left mouse button
|
|
if (rmb)
|
|
{
|
|
return new TrackerManipulator(this) { Snap = !control, PointsOnly = shift };
|
|
}
|
|
|
|
// XButtons are zoom-stepping
|
|
if (xb1 || xb2)
|
|
{
|
|
double d = xb1 ? 0.05 : -0.05;
|
|
return new ZoomStepManipulator(this, d, control);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// The set clipboard text.
|
|
/// </summary>
|
|
/// <param name="text">
|
|
/// The text.
|
|
/// </param>
|
|
private 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");
|
|
}
|
|
}
|
|
}
|
|
} |