4624 lines
198 KiB
C#
4624 lines
198 KiB
C#
//============================================================================
|
||
//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
|
||
//Copyright ?2004 John Champion
|
||
//
|
||
//This library is free software; you can redistribute it and/or
|
||
//modify it under the terms of the GNU Lesser General Public
|
||
//License as published by the Free Software Foundation; either
|
||
//version 2.1 of the License, or (at your option) any later version.
|
||
//
|
||
//This library is distributed in the hope that it will be useful,
|
||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
//Lesser General Public License for more details.
|
||
//
|
||
//You should have received a copy of the GNU Lesser General Public
|
||
//License along with this library; if not, write to the Free Software
|
||
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
//=============================================================================
|
||
|
||
using System;
|
||
using System.ComponentModel;
|
||
using System.Drawing;
|
||
using System.Drawing.Drawing2D;
|
||
using System.Drawing.Text;
|
||
using System.Drawing.Imaging;
|
||
using System.Drawing.Printing;
|
||
using System.Data;
|
||
using System.Globalization;
|
||
using System.IO;
|
||
using System.Resources;
|
||
using System.Reflection;
|
||
using System.Text;
|
||
using System.Windows.Forms;
|
||
using System.Threading;
|
||
|
||
namespace DrawGraph
|
||
{
|
||
/*
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public struct DrawingThreadData
|
||
{
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public Graphics _g;
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public MasterPane _masterPane;
|
||
|
||
// public DrawingThread( Graphics g, MasterPane masterPane )
|
||
// {
|
||
// _g = g;
|
||
// _masterPane = masterPane;
|
||
// }
|
||
}
|
||
*/
|
||
|
||
/// <summary>
|
||
/// The ZedGraphControl class provides a UserControl interface to the
|
||
/// <see cref="ZedGraph"/> class library. This allows ZedGraph to be installed
|
||
/// as a control in the Visual Studio toolbox. You can use the control by simply
|
||
/// dragging it onto a form in the Visual Studio form editor. All graph
|
||
/// attributes are accessible via the <see cref="ZedGraphControl.GraphPane"/>
|
||
/// property.
|
||
/// </summary>
|
||
/// <author> John Champion revised by Jerry Vos </author>
|
||
/// <version> $Revision: 3.82 $ $Date: 2007/04/16 00:03:06 $ </version>
|
||
public partial class ZedGraphControl : UserControl
|
||
{
|
||
|
||
#region Private Fields
|
||
|
||
/// <summary>
|
||
/// This private field contains the instance for the MasterPane object of this control.
|
||
/// You can access the MasterPane object through the public property
|
||
/// <see cref="ZedGraphControl.MasterPane"/>. This is nulled when this Control is
|
||
/// disposed.
|
||
/// </summary>
|
||
private MasterPane _masterPane;
|
||
|
||
/// <summary>
|
||
/// private field that determines if anti-aliased drawing will be forced on. Use the
|
||
/// public property <see cref="ZedGraphControl.IsAntiAlias"/> to access this value.
|
||
/// </summary>
|
||
private bool _isAntiAlias = false;
|
||
|
||
/// <summary>
|
||
/// private field that determines whether or not tooltips will be displayed
|
||
/// when the mouse hovers over data values. Use the public property
|
||
/// <see cref="IsShowPointValues"/> to access this value.
|
||
/// </summary>
|
||
private bool _isShowPointValues = false;
|
||
/// <summary>
|
||
/// private field that determines whether or not tooltips will be displayed
|
||
/// showing the scale values while the mouse is located within the ChartRect.
|
||
/// Use the public property <see cref="IsShowCursorValues"/> to access this value.
|
||
/// </summary>
|
||
private bool _isShowCursorValues = false;
|
||
/// <summary>
|
||
/// private field that determines the format for displaying tooltip values.
|
||
/// This format is passed to <see cref="PointPairBase.ToString(string)"/>.
|
||
/// Use the public property <see cref="PointValueFormat"/> to access this
|
||
/// value.
|
||
/// </summary>
|
||
private string _pointValueFormat = PointPair.DefaultFormat;
|
||
|
||
/// <summary>
|
||
/// private field that determines whether or not the context menu will be available. Use the
|
||
/// public property <see cref="IsShowContextMenu"/> to access this value.
|
||
/// </summary>
|
||
private bool _isShowContextMenu = true;
|
||
|
||
/// <summary>
|
||
/// private field that determines whether or not a message box will be shown in response to
|
||
/// a context menu "Copy" command. Use the
|
||
/// public property <see cref="IsShowCopyMessage"/> to access this value.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Note that, if this value is set to false, the user will receive no indicative feedback
|
||
/// in response to a Copy action.
|
||
/// </remarks>
|
||
private bool _isShowCopyMessage = true;
|
||
|
||
private SaveFileDialog _saveFileDialog = new SaveFileDialog();
|
||
|
||
/// <summary>
|
||
/// private field that determines whether the settings of
|
||
/// <see cref="ZedGraph.PaneBase.IsFontsScaled" /> and <see cref="PaneBase.IsPenWidthScaled" />
|
||
/// will be overridden to true during printing operations.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Printing involves pixel maps that are typically of a dramatically different dimension
|
||
/// than on-screen pixel maps. Therefore, it becomes more important to scale the fonts and
|
||
/// lines to give a printed image that looks like what is shown on-screen. The default
|
||
/// setting for <see cref="ZedGraph.PaneBase.IsFontsScaled" /> is true, but the default
|
||
/// setting for <see cref="PaneBase.IsPenWidthScaled" /> is false.
|
||
/// </remarks>
|
||
/// <value>
|
||
/// A value of true will cause both <see cref="ZedGraph.PaneBase.IsFontsScaled" /> and
|
||
/// <see cref="PaneBase.IsPenWidthScaled" /> to be temporarily set to true during
|
||
/// printing operations.
|
||
/// </value>
|
||
private bool _isPrintScaleAll = true;
|
||
/// <summary>
|
||
/// private field that determines whether or not the visible aspect ratio of the
|
||
/// <see cref="MasterPane" /> <see cref="PaneBase.Rect" /> will be preserved
|
||
/// when printing this <see cref="ZedGraphControl" />.
|
||
/// </summary>
|
||
private bool _isPrintKeepAspectRatio = true;
|
||
/// <summary>
|
||
/// private field that determines whether or not the <see cref="MasterPane" />
|
||
/// <see cref="PaneBase.Rect" /> dimensions will be expanded to fill the
|
||
/// available space when printing this <see cref="ZedGraphControl" />.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// If <see cref="IsPrintKeepAspectRatio" /> is also true, then the <see cref="MasterPane" />
|
||
/// <see cref="PaneBase.Rect" /> dimensions will be expanded to fit as large
|
||
/// a space as possible while still honoring the visible aspect ratio.
|
||
/// </remarks>
|
||
private bool _isPrintFillPage = true;
|
||
|
||
/// <summary>
|
||
/// private field that determines the format for displaying tooltip date values.
|
||
/// This format is passed to <see cref="XDate.ToString(string)"/>.
|
||
/// Use the public property <see cref="PointDateFormat"/> to access this
|
||
/// value.
|
||
/// </summary>
|
||
private string _pointDateFormat = XDate.DefaultFormatStr;
|
||
|
||
/// <summary>
|
||
/// private value that determines whether or not zooming is enabled for the control in the
|
||
/// vertical direction. Use the public property <see cref="IsEnableVZoom"/> to access this
|
||
/// value.
|
||
/// </summary>
|
||
private bool _isEnableVZoom = true;
|
||
/// <summary>
|
||
/// private value that determines whether or not zooming is enabled for the control in the
|
||
/// horizontal direction. Use the public property <see cref="IsEnableHZoom"/> to access this
|
||
/// value.
|
||
/// </summary>
|
||
private bool _isEnableHZoom = true;
|
||
|
||
/// <summary>
|
||
/// private value that determines whether or not point editing is enabled in the
|
||
/// vertical direction. Use the public property <see cref="IsEnableVEdit"/> to access this
|
||
/// value.
|
||
/// </summary>
|
||
private bool _isEnableVEdit = false;
|
||
/// <summary>
|
||
/// private value that determines whether or not point editing is enabled in the
|
||
/// horizontal direction. Use the public property <see cref="IsEnableHEdit"/> to access this
|
||
/// value.
|
||
/// </summary>
|
||
private bool _isEnableHEdit = false;
|
||
|
||
/// <summary>
|
||
/// private value that determines whether or not panning is allowed for the control in the
|
||
/// horizontal direction. Use the
|
||
/// public property <see cref="IsEnableHPan"/> to access this value.
|
||
/// </summary>
|
||
private bool _isEnableHPan = true;
|
||
/// <summary>
|
||
/// private value that determines whether or not panning is allowed for the control in the
|
||
/// vertical direction. Use the
|
||
/// public property <see cref="IsEnableVPan"/> to access this value.
|
||
/// </summary>
|
||
private bool _isEnableVPan = true;
|
||
|
||
// Revision: JCarpenter 10/06
|
||
/// <summary>
|
||
/// Internal variable that indicates if the control can manage selections.
|
||
/// </summary>
|
||
private bool _isEnableSelection = false;
|
||
|
||
private double _zoomStepFraction = 0.1;
|
||
|
||
private ScrollRange _xScrollRange;
|
||
|
||
private ScrollRangeList _yScrollRangeList;
|
||
private ScrollRangeList _y2ScrollRangeList;
|
||
|
||
private bool _isShowHScrollBar = false;
|
||
private bool _isShowVScrollBar = false;
|
||
//private bool isScrollY2 = false;
|
||
private bool _isAutoScrollRange = false;
|
||
|
||
private double _scrollGrace = 0.00; //0.05;
|
||
|
||
private bool _isSynchronizeXAxes = false;
|
||
private bool _isSynchronizeYAxes = false;
|
||
|
||
//private System.Windows.Forms.HScrollBar hScrollBar1;
|
||
//private System.Windows.Forms.VScrollBar vScrollBar1;
|
||
|
||
// The range of values to use the scroll control bars
|
||
private const int _ScrollControlSpan = int.MaxValue;
|
||
// The ratio of the largeChange to the smallChange for the scroll bars
|
||
private const int _ScrollSmallRatio = 10;
|
||
|
||
private bool _isZoomOnMouseCenter = false;
|
||
|
||
private ResourceManager _resourceManager;
|
||
|
||
/// <summary>
|
||
/// private field that stores a <see cref="PrintDocument" /> instance, which maintains
|
||
/// a persistent selection of printer options.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This is needed so that a "Print" action utilizes the settings from a prior
|
||
/// "Page Setup" action.</remarks>
|
||
private PrintDocument _pdSave = null;
|
||
//private PrinterSettings printSave = null;
|
||
//private PageSettings pageSave = null;
|
||
|
||
/// <summary>
|
||
/// This private field contains a list of selected CurveItems.
|
||
/// </summary>
|
||
//private List<CurveItem> _selection = new List<CurveItem>();
|
||
private Selection _selection = new Selection();
|
||
|
||
#endregion
|
||
|
||
#region Fields: Buttons & Keys Properties
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which Mouse button will be used to click on
|
||
/// linkable objects
|
||
/// </summary>
|
||
/// <seealso cref="LinkModifierKeys" />
|
||
private MouseButtons _linkButtons = MouseButtons.Left;
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which modifier keys will be used to click
|
||
/// on linkable objects
|
||
/// </summary>
|
||
/// <seealso cref="LinkButtons" />
|
||
private Keys _linkModifierKeys = Keys.Alt;
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which Mouse button will be used to edit point
|
||
/// data values
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This setting only applies if <see cref="IsEnableHEdit" /> and/or
|
||
/// <see cref="IsEnableVEdit" /> are true.
|
||
/// </remarks>
|
||
/// <seealso cref="EditModifierKeys" />
|
||
private MouseButtons _editButtons = MouseButtons.Right;
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which modifier keys will be used to edit point
|
||
/// data values
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This setting only applies if <see cref="IsEnableHEdit" /> and/or
|
||
/// <see cref="IsEnableVEdit" /> are true.
|
||
/// </remarks>
|
||
/// <seealso cref="EditButtons" />
|
||
private Keys _editModifierKeys = Keys.Alt;
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which mouse button will be used to select
|
||
/// <see cref="CurveItem" />'s.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This setting only applies if <see cref="IsEnableSelection" /> is true.
|
||
/// </remarks>
|
||
/// <seealso cref="SelectModifierKeys" />
|
||
private MouseButtons _selectButtons = MouseButtons.Left;
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which modifier keys will be used to select
|
||
/// <see cref="CurveItem" />'s.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This setting only applies if <see cref="IsEnableSelection" /> is true.
|
||
/// </remarks>
|
||
/// <seealso cref="SelectButtons" />
|
||
private Keys _selectModifierKeys = Keys.Shift;
|
||
|
||
private Keys _selectAppendModifierKeys = Keys.Shift | Keys.Control;
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which Mouse button will be used to perform
|
||
/// zoom operations
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This setting only applies if <see cref="IsEnableHZoom" /> and/or
|
||
/// <see cref="IsEnableVZoom" /> are true.
|
||
/// </remarks>
|
||
/// <seealso cref="ZoomModifierKeys" />
|
||
/// <seealso cref="ZoomButtons2" />
|
||
/// <seealso cref="ZoomModifierKeys2" />
|
||
private MouseButtons _zoomButtons = MouseButtons.Left;
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which modifier keys will be used to perform
|
||
/// zoom operations
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This setting only applies if <see cref="IsEnableHZoom" /> and/or
|
||
/// <see cref="IsEnableVZoom" /> are true.
|
||
/// </remarks>
|
||
/// <seealso cref="ZoomButtons" />
|
||
/// <seealso cref="ZoomButtons2" />
|
||
/// <seealso cref="ZoomModifierKeys2" />
|
||
private Keys _zoomModifierKeys = Keys.None;
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which Mouse button will be used as a
|
||
/// secondary option to perform zoom operations
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This setting only applies if <see cref="IsEnableHZoom" /> and/or
|
||
/// <see cref="IsEnableVZoom" /> are true.
|
||
/// </remarks>
|
||
/// <seealso cref="ZoomModifierKeys2" />
|
||
/// <seealso cref="ZoomButtons" />
|
||
/// <seealso cref="ZoomModifierKeys" />
|
||
private MouseButtons _zoomButtons2 = MouseButtons.None;
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which modifier keys will be used as a
|
||
/// secondary option to perform zoom operations
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This setting only applies if <see cref="IsEnableHZoom" /> and/or
|
||
/// <see cref="IsEnableVZoom" /> are true.
|
||
/// </remarks>
|
||
/// <seealso cref="ZoomButtons" />
|
||
/// <seealso cref="ZoomButtons2" />
|
||
/// <seealso cref="ZoomModifierKeys2" />
|
||
private Keys _zoomModifierKeys2 = Keys.None;
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which Mouse button will be used to perform
|
||
/// panning operations
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This setting only applies if <see cref="IsEnableHPan" /> and/or
|
||
/// <see cref="IsEnableVPan" /> are true. A Pan operation (dragging the graph with
|
||
/// the mouse) should not be confused with a scroll operation (using a scroll bar to
|
||
/// move the graph).
|
||
/// </remarks>
|
||
/// <seealso cref="PanModifierKeys" />
|
||
/// <seealso cref="PanButtons2" />
|
||
/// <seealso cref="PanModifierKeys2" />
|
||
private MouseButtons _panButtons = MouseButtons.Left;
|
||
|
||
// Setting this field to Keys.Shift here
|
||
// causes an apparent bug to crop up in VS 2003, by which it will have the value:
|
||
// "System.Windows.Forms.Keys.Shift+None", which won't compile
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which modifier keys will be used to perform
|
||
/// panning operations
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This setting only applies if <see cref="IsEnableHPan" /> and/or
|
||
/// <see cref="IsEnableVPan" /> are true. A Pan operation (dragging the graph with
|
||
/// the mouse) should not be confused with a scroll operation (using a scroll bar to
|
||
/// move the graph).
|
||
/// </remarks>
|
||
/// <seealso cref="PanButtons" />
|
||
/// <seealso cref="PanButtons2" />
|
||
/// <seealso cref="PanModifierKeys2" />
|
||
private Keys _panModifierKeys = Keys.Control;
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which Mouse button will be used as a
|
||
/// secondary option to perform panning operations
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This setting only applies if <see cref="IsEnableHPan" /> and/or
|
||
/// <see cref="IsEnableVPan" /> are true. A Pan operation (dragging the graph with
|
||
/// the mouse) should not be confused with a scroll operation (using a scroll bar to
|
||
/// move the graph).
|
||
/// </remarks>
|
||
/// <seealso cref="PanModifierKeys2" />
|
||
/// <seealso cref="PanButtons" />
|
||
/// <seealso cref="PanModifierKeys" />
|
||
private MouseButtons _panButtons2 = MouseButtons.Middle;
|
||
|
||
// Setting this field to Keys.Shift here
|
||
// causes an apparent bug to crop up in VS 2003, by which it will have the value:
|
||
// "System.Windows.Forms.Keys.Shift+None", which won't compile
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which modifier keys will be used as a
|
||
/// secondary option to perform panning operations
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This setting only applies if <see cref="IsEnableHPan" /> and/or
|
||
/// <see cref="IsEnableVPan" /> are true. A Pan operation (dragging the graph with
|
||
/// the mouse) should not be confused with a scroll operation (using a scroll bar to
|
||
/// move the graph).
|
||
/// </remarks>
|
||
/// <seealso cref="PanButtons2" />
|
||
/// <seealso cref="PanButtons" />
|
||
/// <seealso cref="PanModifierKeys" />
|
||
private Keys _panModifierKeys2 = Keys.None;
|
||
|
||
#endregion
|
||
|
||
#region Button and Key Properties
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which mouse button will be used as a primary option
|
||
/// to trigger a zoom event.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This value is combined with <see cref="ZoomModifierKeys"/> to determine the actual zoom combination.
|
||
/// A secondary zoom button/key combination option is available via <see cref="ZoomButtons2"/> and
|
||
/// <see cref="ZoomModifierKeys2"/>. To not use this button/key combination, set the value
|
||
/// of <see cref="ZoomButtons"/> to <see cref="MouseButtons.None"/>.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(MouseButtons.Left),
|
||
Description("Determines which mouse button is used as the primary for zooming")]
|
||
public MouseButtons ZoomButtons
|
||
{
|
||
get { return _zoomButtons; }
|
||
set { _zoomButtons = value; }
|
||
}
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which mouse button will be used as the secondary option
|
||
/// to trigger a zoom event.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This value is combined with <see cref="ZoomModifierKeys2"/> to determine the actual zoom combination.
|
||
/// The primary zoom button/key combination option is available via <see cref="ZoomButtons"/> and
|
||
/// <see cref="ZoomModifierKeys"/>. To not use this button/key combination, set the value
|
||
/// of <see cref="ZoomButtons2"/> to <see cref="MouseButtons.None"/>.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(MouseButtons.None),
|
||
Description("Determines which mouse button is used as the secondary for zooming")]
|
||
public MouseButtons ZoomButtons2
|
||
{
|
||
get { return _zoomButtons2; }
|
||
set { _zoomButtons2 = value; }
|
||
}
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which modifier keys will be used as a primary option
|
||
/// to trigger a zoom event.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This value is combined with <see cref="ZoomButtons"/> to determine the actual zoom combination.
|
||
/// A secondary zoom button/key combination option is available via <see cref="ZoomButtons2"/> and
|
||
/// <see cref="ZoomModifierKeys2"/>. To not use this button/key combination, set the value
|
||
/// of <see cref="ZoomButtons"/> to <see cref="MouseButtons.None"/>.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(Keys.None),
|
||
Description("Determines which modifier key used as the primary for zooming")]
|
||
public Keys ZoomModifierKeys
|
||
{
|
||
get { return _zoomModifierKeys; }
|
||
set { _zoomModifierKeys = value; }
|
||
}
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which modifier keys will be used as a secondary option
|
||
/// to trigger a zoom event.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This value is combined with <see cref="ZoomButtons2"/> to determine the actual zoom combination.
|
||
/// A primary zoom button/key combination option is available via <see cref="ZoomButtons"/> and
|
||
/// <see cref="ZoomModifierKeys"/>. To not use this button/key combination, set the value
|
||
/// of <see cref="ZoomButtons2"/> to <see cref="MouseButtons.None"/>.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(Keys.None),
|
||
Description("Determines which modifier key used as the secondary for zooming")]
|
||
public Keys ZoomModifierKeys2
|
||
{
|
||
get { return _zoomModifierKeys2; }
|
||
set { _zoomModifierKeys2 = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which mouse button will be used as a primary option
|
||
/// to trigger a pan event.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This value is combined with <see cref="PanModifierKeys"/> to determine the actual pan combination.
|
||
/// A secondary pan button/key combination option is available via <see cref="PanButtons2"/> and
|
||
/// <see cref="PanModifierKeys2"/>. To not use this button/key combination, set the value
|
||
/// of <see cref="PanButtons"/> to <see cref="MouseButtons.None"/>.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(MouseButtons.Left),
|
||
Description("Determines which mouse button is used as the primary for panning")]
|
||
public MouseButtons PanButtons
|
||
{
|
||
get { return _panButtons; }
|
||
set { _panButtons = value; }
|
||
}
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which mouse button will be used as the secondary option
|
||
/// to trigger a pan event.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This value is combined with <see cref="PanModifierKeys2"/> to determine the actual pan combination.
|
||
/// The primary pan button/key combination option is available via <see cref="PanButtons"/> and
|
||
/// <see cref="PanModifierKeys"/>. To not use this button/key combination, set the value
|
||
/// of <see cref="PanButtons2"/> to <see cref="MouseButtons.None"/>.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(MouseButtons.Middle),
|
||
Description("Determines which mouse button is used as the secondary for panning")]
|
||
public MouseButtons PanButtons2
|
||
{
|
||
get { return _panButtons2; }
|
||
set { _panButtons2 = value; }
|
||
}
|
||
|
||
// NOTE: The default value of PanModifierKeys is Keys.Shift. Because of an apparent bug in
|
||
// VS 2003, the initial value set in InitializeComponent by the code wizard is "Keys.Shift+None"
|
||
// which will not compile. As a temporary workaround, I've hidden the value so that it won't
|
||
// have compile errors. This problem does not exist in VS 2005.
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which modifier keys will be used as a primary option
|
||
/// to trigger a pan event.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This value is combined with <see cref="PanButtons"/> to determine the actual pan combination.
|
||
/// A secondary pan button/key combination option is available via <see cref="PanButtons2"/> and
|
||
/// <see cref="PanModifierKeys2"/>. To not use this button/key combination, set the value
|
||
/// of <see cref="PanButtons"/> to <see cref="MouseButtons.None"/>.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(Keys.Control),
|
||
Description("Determines which modifier key is used as the primary for panning")]
|
||
public Keys PanModifierKeys
|
||
{
|
||
get { return _panModifierKeys; }
|
||
set { _panModifierKeys = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which modifier keys will be used as a secondary option
|
||
/// to trigger a pan event.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This value is combined with <see cref="PanButtons2"/> to determine the actual pan combination.
|
||
/// A primary pan button/key combination option is available via <see cref="PanButtons"/> and
|
||
/// <see cref="PanModifierKeys"/>. To not use this button/key combination, set the value
|
||
/// of <see cref="PanButtons2"/> to <see cref="MouseButtons.None"/>.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(Keys.None),
|
||
Description("Determines which modifier key is used as the secondary for panning")]
|
||
public Keys PanModifierKeys2
|
||
{
|
||
get { return _panModifierKeys2; }
|
||
set { _panModifierKeys2 = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which Mouse button will be used to edit point
|
||
/// data values
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This setting only applies if <see cref="IsEnableHEdit" /> and/or
|
||
/// <see cref="IsEnableVEdit" /> are true.
|
||
/// </remarks>
|
||
/// <seealso cref="EditModifierKeys" />
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(MouseButtons.Right),
|
||
Description("Specify mouse button for point editing")]
|
||
public MouseButtons EditButtons
|
||
{
|
||
get { return _editButtons; }
|
||
set { _editButtons = value; }
|
||
}
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which modifier keys will be used to edit point
|
||
/// data values
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This setting only applies if <see cref="IsEnableHEdit" /> and/or
|
||
/// <see cref="IsEnableVEdit" /> are true.
|
||
/// </remarks>
|
||
/// <seealso cref="EditButtons" />
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(Keys.Alt),
|
||
Description("Specify modifier key for point editing")]
|
||
public Keys EditModifierKeys
|
||
{
|
||
get { return _editModifierKeys; }
|
||
set { _editModifierKeys = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which Mouse button will be used to
|
||
/// select <see cref="CurveItem" />'s.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This setting only applies if <see cref="IsEnableSelection" /> is true.
|
||
/// </remarks>
|
||
/// <seealso cref="SelectModifierKeys" />
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(MouseButtons.Left),
|
||
Description("Specify mouse button for curve selection")]
|
||
public MouseButtons SelectButtons
|
||
{
|
||
get { return _selectButtons; }
|
||
set { _selectButtons = value; }
|
||
}
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which Modifier keys will be used to
|
||
/// select <see cref="CurveItem" />'s.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This setting only applies if <see cref="IsEnableSelection" /> is true.
|
||
/// </remarks>
|
||
/// <seealso cref="SelectButtons" />
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(Keys.Shift),
|
||
Description("Specify modifier key for curve selection")]
|
||
public Keys SelectModifierKeys
|
||
{
|
||
get { return _selectModifierKeys; }
|
||
set { _selectModifierKeys = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which Modifier keys will be used to
|
||
/// append a <see cref="CurveItem" /> to the selection list.
|
||
/// </summary>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(Keys.Shift | Keys.Alt),
|
||
Description("Specify modifier key for append curve selection")]
|
||
public Keys SelectAppendModifierKeys
|
||
{
|
||
get { return _selectAppendModifierKeys; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which Mouse button will be used to click
|
||
/// on linkable objects
|
||
/// </summary>
|
||
/// <seealso cref="LinkModifierKeys" />
|
||
/// <seealso cref="LinkEvent"/>
|
||
// /// <seealso cref="ZedGraph.Web.IsImageMap"/>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(MouseButtons.Left),
|
||
Description("Specify mouse button for clicking on linkable objects")]
|
||
public MouseButtons LinkButtons
|
||
{
|
||
get { return _linkButtons; }
|
||
set { _linkButtons = value; }
|
||
}
|
||
/// <summary>
|
||
/// Gets or sets a value that determines which modifier keys will be used to click
|
||
/// on linkable objects
|
||
/// </summary>
|
||
/// <seealso cref="LinkButtons" />
|
||
/// <seealso cref="LinkEvent"/>
|
||
// /// <seealso cref="ZedGraph.Web.IsImageMap"/>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(Keys.Alt),
|
||
Description("Specify modifier key for clicking on linkable objects")]
|
||
public Keys LinkModifierKeys
|
||
{
|
||
get { return _linkModifierKeys; }
|
||
set { _linkModifierKeys = value; }
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Fields: Temporary state variables
|
||
|
||
/// <summary>
|
||
/// Internal variable that indicates the control is currently being zoomed.
|
||
/// </summary>
|
||
private bool _isZooming = false;
|
||
/// <summary>
|
||
/// Internal variable that indicates the control is currently being panned.
|
||
/// </summary>
|
||
private bool _isPanning = false;
|
||
/// <summary>
|
||
/// Internal variable that indicates a point value is currently being edited.
|
||
/// </summary>
|
||
private bool _isEditing = false;
|
||
|
||
// Revision: JCarpenter 10/06
|
||
/// <summary>
|
||
/// Internal variable that indicates the control is currently using selection.
|
||
/// </summary>
|
||
private bool _isSelecting = false;
|
||
|
||
/// <summary>
|
||
/// Internal variable that stores the <see cref="GraphPane"/> reference for the Pane that is
|
||
/// currently being zoomed or panned.
|
||
/// </summary>
|
||
private GraphPane _dragPane = null;
|
||
/// <summary>
|
||
/// Internal variable that stores a rectangle which is either the zoom rectangle, or the incremental
|
||
/// pan amount since the last mousemove event.
|
||
/// </summary>
|
||
private Point _dragStartPt;
|
||
private Point _dragEndPt;
|
||
|
||
private int _dragIndex;
|
||
private CurveItem _dragCurve;
|
||
private PointPair _dragStartPair;
|
||
/// <summary>
|
||
/// private field that stores the state of the scale ranges prior to starting a panning action.
|
||
/// </summary>
|
||
private ZoomState _zoomState;
|
||
private ZoomStateStack _zoomStateStack;
|
||
|
||
//temporarily save the location of a context menu click so we can use it for reference
|
||
// Note that Control.MousePosition ends up returning the position after the mouse has
|
||
// moved to the menu item within the context menu. Therefore, this point is saved so
|
||
// that we have the point at which the context menu was first right-clicked
|
||
internal Point _menuClickPt;
|
||
|
||
#endregion
|
||
|
||
#region Events
|
||
|
||
/// <summary>
|
||
/// A delegate that allows subscribing methods to append or modify the context menu.
|
||
/// </summary>
|
||
/// <param name="sender">The source <see cref="ZedGraphControl"/> object</param>
|
||
/// <param name="menuStrip">A reference to the <see cref="ContextMenuStrip"/> object
|
||
/// that contains the context menu.
|
||
/// </param>
|
||
/// <param name="mousePt">The point at which the mouse was clicked</param>
|
||
/// <param name="objState">The current context menu state</param>
|
||
/// <seealso cref="ContextMenuBuilder" />
|
||
public delegate void ContextMenuBuilderEventHandler(ZedGraphControl sender,
|
||
ContextMenuStrip menuStrip, Point mousePt, ContextMenuObjectState objState);
|
||
/// <summary>
|
||
/// Subscribe to this event to be able to modify the ZedGraph context menu.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// The context menu is built on the fly after a right mouse click. You can add menu items
|
||
/// to this menu by simply modifying the <see paramref="menu"/> parameter.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Events"),
|
||
Description("Subscribe to this event to be able to modify the ZedGraph context menu")]
|
||
public event ContextMenuBuilderEventHandler ContextMenuBuilder;
|
||
|
||
/// <summary>
|
||
/// A delegate that allows notification of zoom and pan events.
|
||
/// </summary>
|
||
/// <param name="sender">The source <see cref="ZedGraphControl"/> object</param>
|
||
/// <param name="oldState">A <see cref="ZoomState"/> object that corresponds to the state of the
|
||
/// <see cref="GraphPane"/> before the zoom or pan event.</param>
|
||
/// <param name="newState">A <see cref="ZoomState"/> object that corresponds to the state of the
|
||
/// <see cref="GraphPane"/> after the zoom or pan event</param>
|
||
/// <seealso cref="ZoomEvent" />
|
||
public delegate void ZoomEventHandler(ZedGraphControl sender, ZoomState oldState,
|
||
ZoomState newState);
|
||
|
||
/// <summary>
|
||
/// Subscribe to this event to be notified when the <see cref="GraphPane"/> is zoomed or panned by the user,
|
||
/// either via a mouse drag operation or by the context menu commands.
|
||
/// </summary>
|
||
[Bindable(true), Category("Events"),
|
||
Description("Subscribe to this event to be notified when the graph is zoomed or panned")]
|
||
public event ZoomEventHandler ZoomEvent;
|
||
|
||
/// <summary>
|
||
/// A delegate that allows notification of scroll events.
|
||
/// </summary>
|
||
/// <param name="sender">The source <see cref="ZedGraphControl"/> object</param>
|
||
/// <param name="scrollBar">The source <see cref="ScrollBar"/> object</param>
|
||
/// <param name="oldState">A <see cref="ZoomState"/> object that corresponds to the state of the
|
||
/// <see cref="GraphPane"/> before the scroll event.</param>
|
||
/// <param name="newState">A <see cref="ZoomState"/> object that corresponds to the state of the
|
||
/// <see cref="GraphPane"/> after the scroll event</param>
|
||
/// <seealso cref="ZoomEvent" />
|
||
public delegate void ScrollDoneHandler(ZedGraphControl sender, ScrollBar scrollBar,
|
||
ZoomState oldState, ZoomState newState);
|
||
|
||
/// <summary>
|
||
/// Subscribe to this event to be notified when the <see cref="GraphPane"/> is scrolled by the user
|
||
/// using the scrollbars.
|
||
/// </summary>
|
||
[Bindable(true), Category("Events"),
|
||
Description("Subscribe this event to be notified when a scroll operation using the scrollbars is completed")]
|
||
public event ScrollDoneHandler ScrollDoneEvent;
|
||
|
||
/// <summary>
|
||
/// A delegate that allows notification of scroll events.
|
||
/// </summary>
|
||
/// <param name="sender">The source <see cref="ZedGraphControl"/> object</param>
|
||
/// <param name="scrollBar">The source <see cref="ScrollBar"/> object</param>
|
||
/// <param name="oldState">A <see cref="ZoomState"/> object that corresponds to the state of the
|
||
/// <see cref="GraphPane"/> before the scroll event.</param>
|
||
/// <param name="newState">A <see cref="ZoomState"/> object that corresponds to the state of the
|
||
/// <see cref="GraphPane"/> after the scroll event</param>
|
||
/// <seealso cref="ZoomEvent" />
|
||
public delegate void ScrollProgressHandler(ZedGraphControl sender, ScrollBar scrollBar,
|
||
ZoomState oldState, ZoomState newState);
|
||
|
||
/// <summary>
|
||
/// Subscribe to this event to be notified when the <see cref="GraphPane"/> is scrolled by the user
|
||
/// using the scrollbars.
|
||
/// </summary>
|
||
[Bindable(true), Category("Events"),
|
||
Description("Subscribe this event to be notified continuously as a scroll operation is taking place")]
|
||
public event ScrollProgressHandler ScrollProgressEvent;
|
||
|
||
/// <summary>
|
||
/// A delegate that receives notification after a point-edit operation is completed.
|
||
/// </summary>
|
||
/// <param name="sender">The source <see cref="ZedGraphControl"/> object</param>
|
||
/// <param name="pane">The <see cref="GraphPane"/> object that contains the
|
||
/// point that has been edited</param>
|
||
/// <param name="curve">The <see cref="CurveItem"/> object that contains the point
|
||
/// that has been edited</param>
|
||
/// <param name="iPt">The integer index of the edited <see cref="PointPair"/> within the
|
||
/// <see cref="IPointList"/> of the selected <see cref="CurveItem"/>
|
||
/// </param>
|
||
/// <seealso cref="PointValueEvent" />
|
||
public delegate string PointEditHandler(ZedGraphControl sender, GraphPane pane,
|
||
CurveItem curve, int iPt);
|
||
|
||
/// <summary>
|
||
/// Subscribe to this event to receive notifcation and/or respond after a data
|
||
/// point has been edited via <see cref="IsEnableHEdit" /> and <see cref="IsEnableVEdit" />.
|
||
/// </summary>
|
||
/// <example>
|
||
/// <para>To subscribe to this event, use the following in your Form_Load method:</para>
|
||
/// <code>zedGraphControl1.PointEditEvent +=
|
||
/// new ZedGraphControl.PointEditHandler( MyPointEditHandler );</code>
|
||
/// <para>Add this method to your Form1.cs:</para>
|
||
/// <code>
|
||
/// private string MyPointEditHandler( object sender, GraphPane pane, CurveItem curve, int iPt )
|
||
/// {
|
||
/// PointPair pt = curve[iPt];
|
||
/// return "This value is " + pt.Y.ToString("f2") + " gallons";
|
||
/// }</code>
|
||
/// </example>
|
||
[Bindable(true), Category("Events"),
|
||
Description("Subscribe to this event to respond to data point edit actions")]
|
||
public event PointEditHandler PointEditEvent;
|
||
|
||
/// <summary>
|
||
/// A delegate that allows custom formatting of the point value tooltips
|
||
/// </summary>
|
||
/// <param name="sender">The source <see cref="ZedGraphControl"/> object</param>
|
||
/// <param name="pane">The <see cref="GraphPane"/> object that contains the point value of interest</param>
|
||
/// <param name="curve">The <see cref="CurveItem"/> object that contains the point value of interest</param>
|
||
/// <param name="iPt">The integer index of the selected <see cref="PointPair"/> within the
|
||
/// <see cref="IPointList"/> of the selected <see cref="CurveItem"/></param>
|
||
/// <seealso cref="PointValueEvent" />
|
||
public delegate string PointValueHandler(ZedGraphControl sender, GraphPane pane,
|
||
CurveItem curve, int iPt);
|
||
|
||
/// <summary>
|
||
/// Subscribe to this event to provide custom formatting for the tooltips
|
||
/// </summary>
|
||
/// <example>
|
||
/// <para>To subscribe to this event, use the following in your FormLoad method:</para>
|
||
/// <code>zedGraphControl1.PointValueEvent +=
|
||
/// new ZedGraphControl.PointValueHandler( MyPointValueHandler );</code>
|
||
/// <para>Add this method to your Form1.cs:</para>
|
||
/// <code>
|
||
/// private string MyPointValueHandler( object sender, GraphPane pane, CurveItem curve, int iPt )
|
||
/// {
|
||
/// #region
|
||
/// PointPair pt = curve[iPt];
|
||
/// return "This value is " + pt.Y.ToString("f2") + " gallons";
|
||
/// #endregion
|
||
/// }</code>
|
||
/// </example>
|
||
[Bindable(true), Category("Events"),
|
||
Description("Subscribe to this event to provide custom-formatting for data point tooltips")]
|
||
public event PointValueHandler PointValueEvent;
|
||
|
||
/// <summary>
|
||
/// A delegate that allows notification of mouse events on Graph objects.
|
||
/// </summary>
|
||
/// <param name="sender">The source <see cref="ZedGraphControl"/> object</param>
|
||
/// <param name="e">A <see cref="MouseEventArgs" /> corresponding to this event</param>
|
||
/// <seealso cref="MouseDownEvent" />
|
||
/// <returns>
|
||
/// Return true if you have handled the mouse event entirely, and you do not
|
||
/// want the <see cref="ZedGraphControl"/> to do any further action (e.g., starting
|
||
/// a zoom operation). Return false if ZedGraph should go ahead and process the
|
||
/// mouse event.
|
||
/// </returns>
|
||
public delegate bool ZedMouseEventHandler(ZedGraphControl sender, MouseEventArgs e);
|
||
|
||
/// <summary>
|
||
/// Subscribe to this event to provide notification of MouseDown clicks on graph
|
||
/// objects
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This event provides for a notification when the mouse is clicked on an object
|
||
/// within any <see cref="GraphPane"/> of the <see cref="MasterPane"/> associated
|
||
/// with this <see cref="ZedGraphControl" />. This event will use the
|
||
/// <see cref="ZedGraph.MasterPane.FindNearestPaneObject"/> method to determine which object
|
||
/// was clicked. The boolean value that you return from this handler determines whether
|
||
/// or not the <see cref="ZedGraphControl"/> will do any further handling of the
|
||
/// MouseDown event (see <see cref="ZedMouseEventHandler" />). Return true if you have
|
||
/// handled the MouseDown event entirely, and you do not
|
||
/// want the <see cref="ZedGraphControl"/> to do any further action (e.g., starting
|
||
/// a zoom operation). Return false if ZedGraph should go ahead and process the
|
||
/// MouseDown event.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Events"),
|
||
Description("Subscribe to be notified when the left mouse button is clicked down")]
|
||
public event ZedMouseEventHandler MouseDownEvent;
|
||
|
||
/// <summary>
|
||
/// Hide the standard control MouseDown event so that the ZedGraphControl.MouseDownEvent
|
||
/// can be used. This is so that the user must return true/false in order to indicate
|
||
/// whether or not we should respond to the event.
|
||
/// </summary>
|
||
[Bindable(false), Browsable(false)]
|
||
public new event MouseEventHandler MouseDown;
|
||
/// <summary>
|
||
/// Hide the standard control MouseUp event so that the ZedGraphControl.MouseUpEvent
|
||
/// can be used. This is so that the user must return true/false in order to indicate
|
||
/// whether or not we should respond to the event.
|
||
/// </summary>
|
||
[Bindable(false), Browsable(false)]
|
||
public new event MouseEventHandler MouseUp;
|
||
/// <summary>
|
||
/// Hide the standard control MouseMove event so that the ZedGraphControl.MouseMoveEvent
|
||
/// can be used. This is so that the user must return true/false in order to indicate
|
||
/// whether or not we should respond to the event.
|
||
/// </summary>
|
||
[Bindable(false), Browsable(false)]
|
||
private new event MouseEventHandler MouseMove;
|
||
/// <summary>
|
||
/// Subscribe to this event to provide notification of MouseUp clicks on graph
|
||
/// objects
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This event provides for a notification when the mouse is clicked on an object
|
||
/// within any <see cref="GraphPane"/> of the <see cref="MasterPane"/> associated
|
||
/// with this <see cref="ZedGraphControl" />. This event will use the
|
||
/// <see cref="ZedGraph.MasterPane.FindNearestPaneObject"/> method to determine which object
|
||
/// was clicked. The boolean value that you return from this handler determines whether
|
||
/// or not the <see cref="ZedGraphControl"/> will do any further handling of the
|
||
/// MouseUp event (see <see cref="ZedMouseEventHandler" />). Return true if you have
|
||
/// handled the MouseUp event entirely, and you do not
|
||
/// want the <see cref="ZedGraphControl"/> to do any further action (e.g., starting
|
||
/// a zoom operation). Return false if ZedGraph should go ahead and process the
|
||
/// MouseUp event.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Events"),
|
||
Description("Subscribe to be notified when the left mouse button is released")]
|
||
public event ZedMouseEventHandler MouseUpEvent;
|
||
/// <summary>
|
||
/// Subscribe to this event to provide notification of MouseMove events over graph
|
||
/// objects
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This event provides for a notification when the mouse is moving over on the control.
|
||
/// The boolean value that you return from this handler determines whether
|
||
/// or not the <see cref="ZedGraphControl"/> will do any further handling of the
|
||
/// MouseMove event (see <see cref="ZedMouseEventHandler" />). Return true if you
|
||
/// have handled the MouseMove event entirely, and you do not
|
||
/// want the <see cref="ZedGraphControl"/> to do any further action.
|
||
/// Return false if ZedGraph should go ahead and process the MouseMove event.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Events"),
|
||
Description("Subscribe to be notified when the mouse is moved inside the control")]
|
||
public event ZedMouseEventHandler MouseMoveEvent;
|
||
|
||
/// <summary>
|
||
/// Subscribe to this event to provide notification of Double Clicks on graph
|
||
/// objects
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This event provides for a notification when the mouse is double-clicked on an object
|
||
/// within any <see cref="GraphPane"/> of the <see cref="MasterPane"/> associated
|
||
/// with this <see cref="ZedGraphControl" />. This event will use the
|
||
/// <see cref="ZedGraph.MasterPane.FindNearestPaneObject"/> method to determine which object
|
||
/// was clicked. The boolean value that you return from this handler determines whether
|
||
/// or not the <see cref="ZedGraphControl"/> will do any further handling of the
|
||
/// DoubleClick event (see <see cref="ZedMouseEventHandler" />). Return true if you have
|
||
/// handled the DoubleClick event entirely, and you do not
|
||
/// want the <see cref="ZedGraphControl"/> to do any further action.
|
||
/// Return false if ZedGraph should go ahead and process the
|
||
/// DoubleClick event.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Events"),
|
||
Description("Subscribe to be notified when the left mouse button is double-clicked")]
|
||
public event ZedMouseEventHandler DoubleClickEvent;
|
||
|
||
/// <summary>
|
||
/// A delegate that allows notification of clicks on ZedGraph objects that have
|
||
/// active links enabled
|
||
/// </summary>
|
||
/// <param name="sender">The source <see cref="ZedGraphControl"/> object</param>
|
||
/// <param name="pane">The source <see cref="GraphPane" /> in which the click
|
||
/// occurred.
|
||
/// </param>
|
||
/// <param name="source">The source object which was clicked. This is typically
|
||
/// a type of <see cref="CurveItem" /> if a curve point was clicked, or
|
||
/// a type of <see cref="GraphObj" /> if a graph object was clicked.
|
||
/// </param>
|
||
/// <param name="link">The <see cref="Link" /> object, belonging to
|
||
/// <paramref name="source" />, that contains the link information
|
||
/// </param>
|
||
/// <param name="index">An index value, typically used if a <see cref="CurveItem" />
|
||
/// was clicked, indicating the ordinal value of the actual point that was clicked.
|
||
/// </param>
|
||
/// <returns>
|
||
/// Return true if you have handled the LinkEvent entirely, and you do not
|
||
/// want the <see cref="ZedGraphControl"/> to do any further action.
|
||
/// Return false if ZedGraph should go ahead and process the LinkEvent.
|
||
/// </returns>
|
||
public delegate bool LinkEventHandler(ZedGraphControl sender, GraphPane pane,
|
||
object source, Link link, int index);
|
||
|
||
/// <summary>
|
||
/// Subscribe to this event to be able to respond to mouse clicks within linked
|
||
/// objects.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Linked objects are typically either <see cref="GraphObj" /> type objects or
|
||
/// <see cref="CurveItem" /> type objects. These object types can include
|
||
/// hyperlink information allowing for "drill-down" type operation.
|
||
/// </remarks>
|
||
/// <seealso cref="LinkEventHandler"/>
|
||
/// <seealso cref="Link" />
|
||
/// <seealso cref="CurveItem.Link">CurveItem.Link</seealso>
|
||
/// <seealso cref="GraphObj.Link">GraphObj.Link</seealso>
|
||
// /// <seealso cref="ZedGraph.Web.IsImageMap" />
|
||
[Bindable(true), Category("Events"),
|
||
Description("Subscribe to be notified when a link-enabled item is clicked")]
|
||
public event LinkEventHandler LinkEvent;
|
||
|
||
#endregion
|
||
|
||
#region Constructors
|
||
|
||
/// <summary>
|
||
/// Default Constructor
|
||
/// </summary>
|
||
public ZedGraphControl()
|
||
{
|
||
InitializeComponent();
|
||
|
||
// These commands do nothing, but they get rid of the compiler warnings for
|
||
// unused events
|
||
bool b = MouseDown == null || MouseUp == null || MouseMove == null;
|
||
|
||
// Link in these events from the base class, since we disable them from this class.
|
||
base.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ZedGraphControl_MouseDown);
|
||
base.MouseUp += new System.Windows.Forms.MouseEventHandler(this.ZedGraphControl_MouseUp);
|
||
base.MouseMove += new System.Windows.Forms.MouseEventHandler(this.ZedGraphControl_MouseMove);
|
||
|
||
//this.MouseWheel += new System.Windows.Forms.MouseEventHandler( this.ZedGraphControl_MouseWheel );
|
||
|
||
// Use double-buffering for flicker-free updating:
|
||
SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint
|
||
| ControlStyles.DoubleBuffer | ControlStyles.ResizeRedraw, true);
|
||
//isTransparentBackground = false;
|
||
//SetStyle( ControlStyles.Opaque, false );
|
||
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
|
||
//this.BackColor = Color.Transparent;
|
||
|
||
_resourceManager = new ResourceManager("DrawGraph.ZedGraphLocale",
|
||
Assembly.GetExecutingAssembly());
|
||
|
||
Rectangle rect = new Rectangle(0, 0, this.Size.Width, this.Size.Height);
|
||
_masterPane = new MasterPane("", rect);
|
||
_masterPane.Margin.All = 0;
|
||
_masterPane.Title.IsVisible = false;
|
||
|
||
string titleStr = _resourceManager.GetString("title_def");
|
||
string xStr = _resourceManager.GetString("x_title_def");
|
||
string yStr = _resourceManager.GetString("y_title_def");
|
||
|
||
//GraphPane graphPane = new GraphPane( rect, "Title", "X Axis", "Y Axis" );
|
||
GraphPane graphPane = new GraphPane(rect, titleStr, xStr, yStr);
|
||
using (Graphics g = this.CreateGraphics())
|
||
{
|
||
graphPane.AxisChange(g);
|
||
//g.Dispose();
|
||
}
|
||
_masterPane.Add(graphPane);
|
||
|
||
this.hScrollBar1.Minimum = 0;
|
||
this.hScrollBar1.Maximum = 100;
|
||
this.hScrollBar1.Value = 0;
|
||
|
||
this.vScrollBar1.Minimum = 0;
|
||
this.vScrollBar1.Maximum = 100;
|
||
this.vScrollBar1.Value = 0;
|
||
|
||
_xScrollRange = new ScrollRange(true);
|
||
_yScrollRangeList = new ScrollRangeList();
|
||
_y2ScrollRangeList = new ScrollRangeList();
|
||
|
||
_yScrollRangeList.Add(new ScrollRange(true));
|
||
_y2ScrollRangeList.Add(new ScrollRange(false));
|
||
|
||
_zoomState = null;
|
||
_zoomStateStack = new ZoomStateStack();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Clean up any resources being used.
|
||
/// </summary>
|
||
/// <param name="disposing">true if the components should be
|
||
/// disposed, false otherwise</param>
|
||
protected override void Dispose(bool disposing)
|
||
{
|
||
lock (this)
|
||
{
|
||
if (disposing)
|
||
{
|
||
if (components != null)
|
||
components.Dispose();
|
||
}
|
||
base.Dispose(disposing);
|
||
|
||
_masterPane = null;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Properties
|
||
|
||
/// <summary>
|
||
/// Gets or sets the <see cref="ZedGraph.MasterPane"/> property for the control
|
||
/// </summary>
|
||
[Bindable(false), Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public MasterPane MasterPane
|
||
{
|
||
get { lock (this) return _masterPane; }
|
||
set { lock (this) _masterPane = value; }
|
||
}
|
||
|
||
// Testing for Designer attribute
|
||
/*
|
||
Class1 _class1 = null;
|
||
[ Bindable( true ), Browsable( true ), Category( "Data" ), NotifyParentProperty( true ),
|
||
DesignerSerializationVisibility( DesignerSerializationVisibility.Content ),
|
||
Description( "My Class1 Test" )]
|
||
public Class1 Class1
|
||
{
|
||
get { if ( _class1 == null ) _class1 = new Class1(); return _class1; }
|
||
set { _class1 = value; }
|
||
}
|
||
*/
|
||
|
||
/// <summary>
|
||
/// Gets or sets the <see cref="ZedGraph.GraphPane"/> property for the control
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <see cref="ZedGraphControl"/> actually uses a <see cref="MasterPane"/> object
|
||
/// to hold a list of <see cref="GraphPane"/> objects. This property really only
|
||
/// accesses the first <see cref="GraphPane"/> in the list. If there is more
|
||
/// than one <see cref="GraphPane"/>, use the <see cref="MasterPane"/>
|
||
/// indexer property to access any of the <see cref="GraphPane"/> objects.</remarks>
|
||
[
|
||
Bindable(false), Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
|
||
]
|
||
//[
|
||
// Bindable( true ), Browsable( true ), Category( "Data" ), NotifyParentProperty( true ),
|
||
// AttributeProvider( typeof( GraphPane ) ),
|
||
// Description("Access to the primary GraphPane object associated with this control")
|
||
//]
|
||
public GraphPane GraphPane
|
||
{
|
||
get
|
||
{
|
||
// Just return the first GraphPane in the list
|
||
lock (this)
|
||
{
|
||
if (_masterPane != null && _masterPane.PaneList.Count > 0)
|
||
return _masterPane[0];
|
||
else
|
||
return null;
|
||
}
|
||
}
|
||
|
||
set
|
||
{
|
||
lock (this)
|
||
{
|
||
//Clear the list, and replace it with the specified Graphpane
|
||
if (_masterPane != null)
|
||
{
|
||
_masterPane.PaneList.Clear();
|
||
_masterPane.Add(value);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines if all drawing operations for this control
|
||
/// will be forced to operate in Anti-alias mode. Note that if this value is set to
|
||
/// "true", it overrides the setting for sub-objects. Otherwise, the sub-object settings
|
||
/// (such as <see cref="FontSpec.IsAntiAlias"/>)
|
||
/// will be honored.
|
||
/// </summary>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(false),
|
||
Description("true to force all objects to be draw in anti-alias mode")]
|
||
public bool IsAntiAlias
|
||
{
|
||
get { return _isAntiAlias; }
|
||
set { _isAntiAlias = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines whether or not tooltips will be displayed
|
||
/// when the mouse hovers over data values.
|
||
/// </summary>
|
||
/// <remarks>The displayed values are taken from <see cref="PointPair.Tag"/>
|
||
/// if it is a <see cref="System.String"/> type, or <see cref="PointPairBase.ToString()"/>
|
||
/// otherwise (using the <see cref="PointValueFormat" /> as a format string).
|
||
/// Additionally, the user can custom format the values using the
|
||
/// <see cref="PointValueEvent" /> event. Note that <see cref="IsShowPointValues" />
|
||
/// may be overridden by <see cref="IsShowCursorValues" />.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(false),
|
||
Description("true to display tooltips when the mouse hovers over data points")]
|
||
public bool IsShowPointValues
|
||
{
|
||
get { return _isShowPointValues; }
|
||
set { _isShowPointValues = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines whether or not tooltips will be displayed
|
||
/// showing the current scale values when the mouse is within the
|
||
/// <see cref="Chart.Rect" />.
|
||
/// </summary>
|
||
/// <remarks>The displayed values are taken from the current mouse position, and formatted
|
||
/// according to <see cref="PointValueFormat" /> and/or <see cref="PointDateFormat" />. If this
|
||
/// value is set to true, it overrides the <see cref="IsShowPointValues" /> setting.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(false),
|
||
Description("true to display tooltips showing the current mouse position within the Chart area")]
|
||
public bool IsShowCursorValues
|
||
{
|
||
get { return _isShowCursorValues; }
|
||
set { _isShowCursorValues = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines whether or not editing of point data is allowed in
|
||
/// the horizontal direction.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Editing is done by holding down the Alt key, and left-clicking on an individual point of
|
||
/// a given <see cref="CurveItem" /> to drag it to a new location. The Mouse and Key
|
||
/// combination for this mode are modifiable using <see cref="EditButtons" /> and
|
||
/// <see cref="EditModifierKeys" />.
|
||
/// </remarks>
|
||
/// <seealso cref="EditButtons" />
|
||
/// <seealso cref="EditModifierKeys" />
|
||
/// <seealso cref="IsEnableVEdit" />
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(false),
|
||
Description("true to allow horizontal editing by alt-left-click-drag")]
|
||
public bool IsEnableHEdit
|
||
{
|
||
get { return _isEnableHEdit; }
|
||
set { _isEnableHEdit = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines whether or not editing of point data is allowed in
|
||
/// the vertical direction.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Editing is done by holding down the Alt key, and left-clicking on an individual point of
|
||
/// a given <see cref="CurveItem" /> to drag it to a new location. The Mouse and Key
|
||
/// combination for this mode are modifiable using <see cref="EditButtons" /> and
|
||
/// <see cref="EditModifierKeys" />.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(false),
|
||
Description("true to allow vertical editing by alt-left-click-drag")]
|
||
public bool IsEnableVEdit
|
||
{
|
||
get { return _isEnableVEdit; }
|
||
set { _isEnableVEdit = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines whether or not zooming is allowed for the control.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Zooming is done by left-clicking inside the <see cref="Chart.Rect"/> to drag
|
||
/// out a rectangle, indicating the new scale ranges that will be part of the graph.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(true),
|
||
Description("true to allow horizontal and vertical zooming by left-click-drag")]
|
||
public bool IsEnableZoom
|
||
{
|
||
set { _isEnableHZoom = value; _isEnableVZoom = value; }
|
||
}
|
||
/// <summary>
|
||
/// Gets or sets a value that determines whether or not zooming is allowed for the control in
|
||
/// the horizontal direction.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Zooming is done by left-clicking inside the <see cref="Chart.Rect"/> to drag
|
||
/// out a rectangle, indicating the new scale ranges that will be part of the graph.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(true),
|
||
Description("true to allow horizontal zooming by left-click-drag")]
|
||
public bool IsEnableHZoom
|
||
{
|
||
get { return _isEnableHZoom; }
|
||
set { _isEnableHZoom = value; }
|
||
}
|
||
/// <summary>
|
||
/// Gets or sets a value that determines whether or not zooming is allowed for the control in
|
||
/// the vertical direction.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Zooming is done by left-clicking inside the <see cref="Chart.Rect"/> to drag
|
||
/// out a rectangle, indicating the new scale ranges that will be part of the graph.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(true),
|
||
Description("true to allow vertical zooming by left-click-drag")]
|
||
public bool IsEnableVZoom
|
||
{
|
||
get { return _isEnableVZoom; }
|
||
set { _isEnableVZoom = value; }
|
||
}
|
||
/// <summary>
|
||
/// Gets or sets a value that determines whether or not panning is allowed for the control in
|
||
/// the horizontal direction.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Panning is done by clicking the middle mouse button (or holding down the shift key
|
||
/// while clicking the left mouse button) inside the <see cref="Chart.Rect"/> and
|
||
/// dragging the mouse around to shift the scale ranges as desired.
|
||
/// </remarks>
|
||
/// <seealso cref="IsEnableVPan"/>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(true),
|
||
Description("true to allow horizontal panning by middle-mouse-drag or shift-left-drag")]
|
||
public bool IsEnableHPan
|
||
{
|
||
get { return _isEnableHPan; }
|
||
set { _isEnableHPan = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines whether or not panning is allowed for the control in
|
||
/// the vertical direction.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Panning is done by clicking the middle mouse button (or holding down the shift key
|
||
/// while clicking the left mouse button) inside the <see cref="Chart.Rect"/> and
|
||
/// dragging the mouse around to shift the scale ranges as desired.
|
||
/// </remarks>
|
||
/// <seealso cref="IsEnableHPan"/>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(true),
|
||
Description("true to allow vertical panning by middle-mouse-drag or shift-left-drag")]
|
||
public bool IsEnableVPan
|
||
{
|
||
get { return _isEnableVPan; }
|
||
set { _isEnableVPan = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines whether or not the context menu will be available.
|
||
/// </summary>
|
||
/// <remarks>The context menu is a menu that appears when you right-click on the
|
||
/// <see cref="ZedGraphControl"/>. It provides options for Zoom, Pan, AutoScale, Clipboard
|
||
/// Copy, and toggle <see cref="IsShowPointValues"/>.
|
||
/// </remarks>
|
||
/// <value>true to allow the context menu, false to disable it</value>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(true),
|
||
Description("true to enable the right mouse button context menu")]
|
||
public bool IsShowContextMenu
|
||
{
|
||
get { return _isShowContextMenu; }
|
||
set { _isShowContextMenu = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines whether or not a message box will be shown
|
||
/// in response to a context menu "Copy" command.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Note that, if this property is set to false, the user will receive no
|
||
/// indicative feedback in response to a Copy action.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(true),
|
||
Description("true to show a message box after a 'Copy' context menu action completes")]
|
||
public bool IsShowCopyMessage
|
||
{
|
||
get { return _isShowCopyMessage; }
|
||
set { _isShowCopyMessage = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the <see cref="SaveFileDialog" /> instance that will be used
|
||
/// by the "Save As..." context menu item.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This provides the opportunity to modify the dialog, such as setting the
|
||
/// <see cref="FileDialog.InitialDirectory" /> property.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(true),
|
||
Description("Provides access to the SaveFileDialog for the 'Save As' menu item")]
|
||
public SaveFileDialog SaveFileDialog
|
||
{
|
||
get { return _saveFileDialog; }
|
||
set { _saveFileDialog = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines whether or not the visible aspect ratio of the
|
||
/// <see cref="MasterPane" /> <see cref="PaneBase.Rect" /> will be preserved
|
||
/// when printing this <see cref="ZedGraphControl" />.
|
||
/// </summary>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(true),
|
||
Description("true to preserve the displayed aspect ratio when printing")]
|
||
public bool IsPrintKeepAspectRatio
|
||
{
|
||
get { return _isPrintKeepAspectRatio; }
|
||
set { _isPrintKeepAspectRatio = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines whether or not the <see cref="MasterPane" />
|
||
/// <see cref="PaneBase.Rect" /> dimensions will be expanded to fill the
|
||
/// available space when printing this <see cref="ZedGraphControl" />.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// If <see cref="IsPrintKeepAspectRatio" /> is also true, then the <see cref="MasterPane" />
|
||
/// <see cref="PaneBase.Rect" /> dimensions will be expanded to fit as large
|
||
/// a space as possible while still honoring the visible aspect ratio.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(true),
|
||
Description("true to resize to fill the page when printing")]
|
||
public bool IsPrintFillPage
|
||
{
|
||
get { return _isPrintFillPage; }
|
||
set { _isPrintFillPage = value; }
|
||
}
|
||
/// <summary>
|
||
/// Gets or sets a value that determines whether the settings of
|
||
/// <see cref="ZedGraph.PaneBase.IsFontsScaled" /> and <see cref="PaneBase.IsPenWidthScaled" />
|
||
/// will be overridden to true during printing operations.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Printing involves pixel maps that are typically of a dramatically different dimension
|
||
/// than on-screen pixel maps. Therefore, it becomes more important to scale the fonts and
|
||
/// lines to give a printed image that looks like what is shown on-screen. The default
|
||
/// setting for <see cref="ZedGraph.PaneBase.IsFontsScaled" /> is true, but the default
|
||
/// setting for <see cref="PaneBase.IsPenWidthScaled" /> is false.
|
||
/// </remarks>
|
||
/// <value>
|
||
/// A value of true will cause both <see cref="ZedGraph.PaneBase.IsFontsScaled" /> and
|
||
/// <see cref="PaneBase.IsPenWidthScaled" /> to be temporarily set to true during
|
||
/// printing operations.
|
||
/// </value>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(true),
|
||
Description("true to force font and pen width scaling when printing")]
|
||
public bool IsPrintScaleAll
|
||
{
|
||
get { return _isPrintScaleAll; }
|
||
set { _isPrintScaleAll = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that controls whether or not the axis value range for the scroll
|
||
/// bars will be set automatically.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// If this value is set to true, then the range of the scroll bars will be set automatically
|
||
/// to the actual range of the data as returned by <see cref="CurveList.GetRange" /> at the
|
||
/// time that <see cref="AxisChange" /> was last called. Note that a value of true
|
||
/// can override any setting of <see cref="ScrollMinX" />, <see cref="ScrollMaxX" />,
|
||
/// <see cref="ScrollMinY" />, <see cref="ScrollMaxY" />,
|
||
/// <see cref="ScrollMinY2" />, and <see cref="ScrollMaxY2" />. Note also that you must
|
||
/// call <see cref="AxisChange" /> from the <see cref="ZedGraphControl" /> for this to
|
||
/// work properly (e.g., don't call it directly from the <see cref="GraphPane" />.
|
||
/// Alternatively, you can call <see cref="SetScrollRangeFromData" /> at anytime to set
|
||
/// the scroll bar range.<br />
|
||
/// <b>In most cases, you will probably want to disable
|
||
/// <see cref="ZedGraph.GraphPane.IsBoundedRanges" /> before activating this option.</b>
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(false),
|
||
Description("true to automatically set the scroll bar range to the actual data range")]
|
||
public bool IsAutoScrollRange
|
||
{
|
||
get { return _isAutoScrollRange; }
|
||
set { _isAutoScrollRange = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Set a "grace" value that leaves a buffer area around the data when
|
||
/// <see cref="IsAutoScrollRange" /> is true.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This value represents a fraction of the total range around each axis. For example, if the
|
||
/// axis ranges from 0 to 100, then a 0.05 value for ScrollGrace would set the scroll range
|
||
/// to -5 to 105.
|
||
/// </remarks>
|
||
public double ScrollGrace
|
||
{
|
||
get { return _scrollGrace; }
|
||
set { _scrollGrace = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines if the horizontal scroll bar will be visible.
|
||
/// </summary>
|
||
/// <remarks>This scroll bar allows the display to be scrolled in the horizontal direction.
|
||
/// Another option is display panning, in which the user can move the display around by
|
||
/// clicking directly on it and dragging (see <see cref="IsEnableHPan"/> and <see cref="IsEnableVPan"/>).
|
||
/// You can control the available range of scrolling with the <see cref="ScrollMinX"/> and
|
||
/// <see cref="ScrollMaxX"/> properties. Note that the scroll range can be set automatically by
|
||
/// <see cref="IsAutoScrollRange" />.<br />
|
||
/// <b>In most cases, you will probably want to disable
|
||
/// <see cref="ZedGraph.GraphPane.IsBoundedRanges" /> before activating this option.</b>
|
||
/// </remarks>
|
||
/// <value>A boolean value. true to display a horizontal scrollbar, false otherwise.</value>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(false),
|
||
Description("true to display the horizontal scroll bar")]
|
||
public bool IsShowHScrollBar
|
||
{
|
||
get { return _isShowHScrollBar; }
|
||
set { _isShowHScrollBar = value; ZedGraphControl_ReSize(this, new EventArgs()); }
|
||
}
|
||
/// <summary>
|
||
/// Gets or sets a value that determines if the vertical scroll bar will be visible.
|
||
/// </summary>
|
||
/// <remarks>This scroll bar allows the display to be scrolled in the vertical direction.
|
||
/// Another option is display panning, in which the user can move the display around by
|
||
/// clicking directly on it and dragging (see <see cref="IsEnableHPan"/> and <see cref="IsEnableVPan"/>).
|
||
/// You can control the available range of scrolling with the <see cref="ScrollMinY"/> and
|
||
/// <see cref="ScrollMaxY"/> properties.
|
||
/// Note that the vertical scroll bar only affects the <see cref="YAxis"/>; it has no impact on
|
||
/// the <see cref="Y2Axis"/>. The panning options affect both the <see cref="YAxis"/> and
|
||
/// <see cref="Y2Axis"/>. Note also that the scroll range can be set automatically by
|
||
/// <see cref="IsAutoScrollRange" />.<br />
|
||
/// <b>In most cases, you will probably want to disable
|
||
/// <see cref="ZedGraph.GraphPane.IsBoundedRanges" /> before activating this option.</b>
|
||
/// </remarks>
|
||
/// <value>A boolean value. true to display a vertical scrollbar, false otherwise.</value>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(false),
|
||
Description("true to display the vertical scroll bar")]
|
||
public bool IsShowVScrollBar
|
||
{
|
||
get { return _isShowVScrollBar; }
|
||
set { _isShowVScrollBar = value; ZedGraphControl_ReSize(this, new EventArgs()); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines if the <see cref="XAxis" /> <see cref="Scale" />
|
||
/// ranges for all <see cref="GraphPane" /> objects in the <see cref="MasterPane" /> will
|
||
/// be forced to match.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// If set to true (default is false), then all of the <see cref="GraphPane" /> objects
|
||
/// in the <see cref="MasterPane" /> associated with this <see cref="ZedGraphControl" />
|
||
/// will be forced to have matching scale ranges for the x axis. That is, zoom, pan,
|
||
/// and scroll operations will result in zoom/pan/scroll for all graphpanes simultaneously.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(false),
|
||
Description("true to force the X axis ranges for all GraphPanes to match")]
|
||
public bool IsSynchronizeXAxes
|
||
{
|
||
get { return _isSynchronizeXAxes; }
|
||
set
|
||
{
|
||
if (_isSynchronizeXAxes != value)
|
||
ZoomStatePurge();
|
||
_isSynchronizeXAxes = value;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines if the <see cref="YAxis" /> <see cref="Scale" />
|
||
/// ranges for all <see cref="GraphPane" /> objects in the <see cref="MasterPane" /> will
|
||
/// be forced to match.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// If set to true (default is false), then all of the <see cref="GraphPane" /> objects
|
||
/// in the <see cref="MasterPane" /> associated with this <see cref="ZedGraphControl" />
|
||
/// will be forced to have matching scale ranges for the y axis. That is, zoom, pan,
|
||
/// and scroll operations will result in zoom/pan/scroll for all graphpanes simultaneously.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(false),
|
||
Description("true to force the Y axis ranges for all GraphPanes to match")]
|
||
public bool IsSynchronizeYAxes
|
||
{
|
||
get { return _isSynchronizeYAxes; }
|
||
set
|
||
{
|
||
if (_isSynchronizeYAxes != value)
|
||
ZoomStatePurge();
|
||
_isSynchronizeYAxes = value;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines if the vertical scroll bar will affect the Y2 axis.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// The vertical scroll bar is automatically associated with the Y axis. With this value, you
|
||
/// can choose to include or exclude the Y2 axis with the scrolling. Note that the Y2 axis
|
||
/// scrolling is handled as a secondary. The vertical scroll bar position always reflects
|
||
/// the status of the Y axis. This can cause the Y2 axis to "jump" when first scrolled if
|
||
/// the <see cref="ScrollMinY2" /> and <see cref="ScrollMaxY2" /> values are not set to the
|
||
/// same proportions as <see cref="ScrollMinY" /> and <see cref="ScrollMaxY" /> with respect
|
||
/// to the actual <see cref="Scale.Min"/> and <see cref="Scale.Max" />. Also note that
|
||
/// this property is actually just an alias to the <see cref="ScrollRange.IsScrollable" />
|
||
/// property of the first element of <see cref="YScrollRangeList" />.
|
||
/// </remarks>
|
||
/// <seealso cref="IsShowVScrollBar"/>
|
||
/// <seealso cref="ScrollMinY2"/>
|
||
/// <seealso cref="ScrollMaxY2"/>
|
||
/// <seealso cref="YScrollRangeList" />
|
||
/// <seealso cref="Y2ScrollRangeList" />
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(false),
|
||
Description("true to scroll the Y2 axis along with the Y axis")]
|
||
public bool IsScrollY2
|
||
{
|
||
get
|
||
{
|
||
if (_y2ScrollRangeList != null && _y2ScrollRangeList.Count > 0)
|
||
return _y2ScrollRangeList[0].IsScrollable;
|
||
else
|
||
return false;
|
||
}
|
||
set
|
||
{
|
||
if (_y2ScrollRangeList != null && _y2ScrollRangeList.Count > 0)
|
||
{
|
||
ScrollRange tmp = _y2ScrollRangeList[0];
|
||
tmp.IsScrollable = value;
|
||
_y2ScrollRangeList[0] = tmp;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Access the <see cref="ScrollRangeList" /> for the Y axes.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This list maintains the user scale ranges for the scroll bars for each axis
|
||
/// in the <see cref="ZedGraph.GraphPane.YAxisList" />. Each ordinal location in
|
||
/// <see cref="YScrollRangeList" /> corresponds to an equivalent ordinal location
|
||
/// in <see cref="ZedGraph.GraphPane.YAxisList" />.
|
||
/// </remarks>
|
||
/// <seealso cref="ScrollMinY" />
|
||
/// <seealso cref="ScrollMaxY" />
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true)]
|
||
[Description("Sets the manual scroll bar ranges for the collection of Y axes")]
|
||
public ScrollRangeList YScrollRangeList
|
||
{
|
||
get { return _yScrollRangeList; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Access the <see cref="ScrollRangeList" /> for the Y2 axes.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This list maintains the user scale ranges for the scroll bars for each axis
|
||
/// in the <see cref="ZedGraph.GraphPane.Y2AxisList" />. Each ordinal location in
|
||
/// <see cref="Y2ScrollRangeList" /> corresponds to an equivalent ordinal location
|
||
/// in <see cref="ZedGraph.GraphPane.Y2AxisList" />.
|
||
/// </remarks>
|
||
/// <seealso cref="ScrollMinY2" />
|
||
/// <seealso cref="ScrollMaxY2" />
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true)]
|
||
[Description("Sets the manual scroll bar ranges for the collection of Y2 axes")]
|
||
public ScrollRangeList Y2ScrollRangeList
|
||
{
|
||
get { return _y2ScrollRangeList; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// The minimum value for the X axis scroll range.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Effectively, the minimum endpoint of the scroll range will cause the
|
||
/// <see cref="Scale.Min"/> value to be set to <see cref="ScrollMinX"/>. Note that this
|
||
/// value applies only to the scroll bar settings. Axis panning (see <see cref="IsEnableHPan"/>)
|
||
/// is not affected by this value. Note that this value can be overridden by
|
||
/// <see cref="IsAutoScrollRange" /> and <see cref="SetScrollRangeFromData" />.
|
||
/// </remarks>
|
||
/// <value>A double value indicating the minimum axis value</value>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(0),
|
||
Description("Sets the manual scroll minimum value for the X axis")]
|
||
public double ScrollMinX
|
||
{
|
||
get { return _xScrollRange.Min; }
|
||
set { _xScrollRange.Min = value; }
|
||
}
|
||
/// <summary>
|
||
/// The maximum value for the X axis scroll range.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Effectively, the maximum endpoint of the scroll range will cause the
|
||
/// <see cref="Scale.Max"/> value to be set to <see cref="ScrollMaxX"/>. Note that this
|
||
/// value applies only to the scroll bar settings. Axis panning (see <see cref="IsEnableHPan"/>)
|
||
/// is not affected by this value. Note that this value can be overridden by
|
||
/// <see cref="IsAutoScrollRange" /> and <see cref="SetScrollRangeFromData" />.
|
||
/// </remarks>
|
||
/// <value>A double value indicating the maximum axis value</value>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(0),
|
||
Description("Sets the manual scroll maximum value for the X axis")]
|
||
public double ScrollMaxX
|
||
{
|
||
get { return _xScrollRange.Max; }
|
||
set { _xScrollRange.Max = value; }
|
||
}
|
||
/// <summary>
|
||
/// The minimum value for the Y axis scroll range.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Effectively, the minimum endpoint of the scroll range will cause the
|
||
/// <see cref="Scale.Min"/> value to be set to <see cref="ScrollMinY"/>. Note that this
|
||
/// value applies only to the scroll bar settings. Axis panning (see <see cref="IsEnableVPan"/>)
|
||
/// is not affected by this value. Note that this value can be overridden by
|
||
/// <see cref="IsAutoScrollRange" /> and <see cref="SetScrollRangeFromData" />. Also note that
|
||
/// this property is actually just an alias to the <see cref="ScrollRange.Min" />
|
||
/// property of the first element of <see cref="YScrollRangeList" />.
|
||
/// </remarks>
|
||
/// <value>A double value indicating the minimum axis value</value>
|
||
/// <seealso cref="YScrollRangeList" />
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(0),
|
||
Description("Sets the manual scroll minimum value for the Y axis")]
|
||
public double ScrollMinY
|
||
{
|
||
get
|
||
{
|
||
if (_yScrollRangeList != null && _yScrollRangeList.Count > 0)
|
||
return _yScrollRangeList[0].Min;
|
||
else
|
||
return double.NaN;
|
||
}
|
||
set
|
||
{
|
||
if (_yScrollRangeList != null && _yScrollRangeList.Count > 0)
|
||
{
|
||
ScrollRange tmp = _yScrollRangeList[0];
|
||
tmp.Min = value;
|
||
_yScrollRangeList[0] = tmp;
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// The maximum value for the Y axis scroll range.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Effectively, the maximum endpoint of the scroll range will cause the
|
||
/// <see cref="Scale.Max"/> value to be set to <see cref="ScrollMaxY"/>. Note that this
|
||
/// value applies only to the scroll bar settings. Axis panning (see <see cref="IsEnableVPan"/>)
|
||
/// is not affected by this value. Note that this value can be overridden by
|
||
/// <see cref="IsAutoScrollRange" /> and <see cref="SetScrollRangeFromData" />. Also note that
|
||
/// this property is actually just an alias to the <see cref="ScrollRange.Max" />
|
||
/// property of the first element of <see cref="YScrollRangeList" />.
|
||
/// </remarks>
|
||
/// <value>A double value indicating the maximum axis value</value>
|
||
/// <seealso cref="YScrollRangeList" />
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(0),
|
||
Description("Sets the manual scroll maximum value for the Y axis")]
|
||
public double ScrollMaxY
|
||
{
|
||
get
|
||
{
|
||
if (_yScrollRangeList != null && _yScrollRangeList.Count > 0)
|
||
return _yScrollRangeList[0].Max;
|
||
else
|
||
return double.NaN;
|
||
}
|
||
set
|
||
{
|
||
if (_yScrollRangeList != null && _yScrollRangeList.Count > 0)
|
||
{
|
||
ScrollRange tmp = _yScrollRangeList[0];
|
||
tmp.Max = value;
|
||
_yScrollRangeList[0] = tmp;
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// The minimum value for the Y2 axis scroll range.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Effectively, the minimum endpoint of the scroll range will cause the
|
||
/// <see cref="Scale.Min"/> value to be set to <see cref="ScrollMinY2"/>. Note that this
|
||
/// value applies only to the scroll bar settings. Axis panning (see <see cref="IsEnableVPan"/>)
|
||
/// is not affected by this value. Note that this value can be overridden by
|
||
/// <see cref="IsAutoScrollRange" /> and <see cref="SetScrollRangeFromData" />. Also note that
|
||
/// this property is actually just an alias to the <see cref="ScrollRange.Min" />
|
||
/// property of the first element of <see cref="Y2ScrollRangeList" />.
|
||
/// </remarks>
|
||
/// <value>A double value indicating the minimum axis value</value>
|
||
/// <seealso cref="Y2ScrollRangeList" />
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(0),
|
||
Description("Sets the manual scroll minimum value for the Y2 axis")]
|
||
public double ScrollMinY2
|
||
{
|
||
get
|
||
{
|
||
if (_y2ScrollRangeList != null && _y2ScrollRangeList.Count > 0)
|
||
return _y2ScrollRangeList[0].Min;
|
||
else
|
||
return double.NaN;
|
||
}
|
||
set
|
||
{
|
||
if (_y2ScrollRangeList != null && _y2ScrollRangeList.Count > 0)
|
||
{
|
||
ScrollRange tmp = _y2ScrollRangeList[0];
|
||
tmp.Min = value;
|
||
_y2ScrollRangeList[0] = tmp;
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// The maximum value for the Y2 axis scroll range.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Effectively, the maximum endpoint of the scroll range will cause the
|
||
/// <see cref="Scale.Max"/> value to be set to <see cref="ScrollMaxY2"/>. Note that this
|
||
/// value applies only to the scroll bar settings. Axis panning (see <see cref="IsEnableVPan"/>)
|
||
/// is not affected by this value. Note that this value can be overridden by
|
||
/// <see cref="IsAutoScrollRange" /> and <see cref="SetScrollRangeFromData" />. Also note that
|
||
/// this property is actually just an alias to the <see cref="ScrollRange.Max" />
|
||
/// property of the first element of <see cref="Y2ScrollRangeList" />.
|
||
/// </remarks>
|
||
/// <value>A double value indicating the maximum axis value</value>
|
||
/// <seealso cref="Y2ScrollRangeList" />
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(0),
|
||
Description("Sets the manual scroll maximum value for the Y2 axis")]
|
||
public double ScrollMaxY2
|
||
{
|
||
get
|
||
{
|
||
if (_y2ScrollRangeList != null && _y2ScrollRangeList.Count > 0)
|
||
return _y2ScrollRangeList[0].Max;
|
||
else
|
||
return double.NaN;
|
||
}
|
||
set
|
||
{
|
||
if (_y2ScrollRangeList != null && _y2ScrollRangeList.Count > 0)
|
||
{
|
||
ScrollRange tmp = _y2ScrollRangeList[0];
|
||
tmp.Max = value;
|
||
_y2ScrollRangeList[0] = tmp;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Returns true if the user is currently scrolling via the scrollbar, or
|
||
/// false if no scrolling is taking place.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This method just tests ScrollBar.Capture to see if the
|
||
/// mouse has been captured by the scroll bar. If so, scrolling is active.
|
||
/// </remarks>
|
||
public Boolean IsScrolling
|
||
{
|
||
get
|
||
{
|
||
if (hScrollBar1 != null && vScrollBar1 != null)
|
||
return hScrollBar1.Capture || vScrollBar1.Capture;
|
||
else
|
||
return false;
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Gets or sets the format for displaying tooltip values.
|
||
/// This format is passed to <see cref="PointPairBase.ToString(string)"/>.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Use the <see cref="System.Globalization.NumberFormatInfo" /> type
|
||
/// to determine the format strings.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(PointPair.DefaultFormat),
|
||
Description("Sets the numeric display format string for the point value tooltips")]
|
||
public string PointValueFormat
|
||
{
|
||
get { return _pointValueFormat; }
|
||
set { _pointValueFormat = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the format for displaying tooltip values.
|
||
/// This format is passed to <see cref="XDate.ToString(string)"/>.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Use the <see cref="System.Globalization.DateTimeFormatInfo" /> type
|
||
/// to determine the format strings.
|
||
/// </remarks>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(XDate.DefaultFormatStr),
|
||
Description("Sets the date display format for the point value tooltips")]
|
||
public string PointDateFormat
|
||
{
|
||
get { return _pointDateFormat; }
|
||
set { _pointDateFormat = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the step size fraction for zooming with the mouse wheel.
|
||
/// A value of 0.1 will result in a 10% zoom step for each mouse wheel movement.
|
||
/// </summary>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(0.1),
|
||
Description("Sets the step size fraction for zooming with the mouse wheel")]
|
||
public double ZoomStepFraction
|
||
{
|
||
get { return _zoomStepFraction; }
|
||
set { _zoomStepFraction = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a boolean value that determines if zooming with the wheel mouse
|
||
/// is centered on the mouse location, or centered on the existing graph.
|
||
/// </summary>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(false),
|
||
Description("true to center the mouse wheel zoom at the current mouse location")]
|
||
public bool IsZoomOnMouseCenter
|
||
{
|
||
get { return _isZoomOnMouseCenter; }
|
||
set { _isZoomOnMouseCenter = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets the graph pane's current image.
|
||
/// <seealso cref="Bitmap"/>
|
||
/// </summary>
|
||
/// <exception cref="ZException">
|
||
/// When the control has been disposed before this call.
|
||
/// </exception>
|
||
[Bindable(false), Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public Image GetImage()
|
||
{
|
||
lock (this)
|
||
{
|
||
if (BeenDisposed || _masterPane == null || _masterPane[0] == null)
|
||
throw new ZException("The control has been disposed");
|
||
|
||
return _masterPane.GetImage();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// This checks if the control has been disposed. This is synonymous with
|
||
/// the graph pane having been nulled or disposed. Therefore this is the
|
||
/// same as <c>ZedGraphControl.GraphPane == null</c>.
|
||
/// </summary>
|
||
[Bindable(false), Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public bool BeenDisposed
|
||
{
|
||
get
|
||
{
|
||
lock (this) return _masterPane == null;
|
||
}
|
||
}
|
||
|
||
// Revision: JCarpenter 10/06
|
||
/// <summary>
|
||
/// Readonly property that gets the list of selected CurveItems
|
||
/// </summary>
|
||
public Selection Selection
|
||
{
|
||
get { return _selection; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that determines whether or not selection is allowed for the control.
|
||
/// </summary>
|
||
[Bindable(true), Category("Display"), NotifyParentProperty(true),
|
||
DefaultValue(false),
|
||
Description("true to allow selecting Curves")]
|
||
public bool IsEnableSelection
|
||
{
|
||
get { return _isEnableSelection; }
|
||
set
|
||
{
|
||
_isEnableSelection = value;
|
||
|
||
/*
|
||
if ( value )
|
||
{
|
||
this.Cursor = Cursors.Default;
|
||
this.IsEnableZoom = false;
|
||
}
|
||
else
|
||
{
|
||
this.Cursor = Cursors.Cross;
|
||
this.IsEnableZoom = true;
|
||
}
|
||
*/
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Methods
|
||
|
||
/// <summary>
|
||
/// Called by the system to update the control on-screen
|
||
/// </summary>
|
||
/// <param name="e">
|
||
/// A PaintEventArgs object containing the Graphics specifications
|
||
/// for this Paint event.
|
||
/// </param>
|
||
protected override void OnPaint(PaintEventArgs e)
|
||
{
|
||
lock (this)
|
||
{
|
||
if (BeenDisposed || _masterPane == null || this.GraphPane == null)
|
||
return;
|
||
|
||
if (hScrollBar1 != null && this.GraphPane != null &&
|
||
vScrollBar1 != null && _yScrollRangeList != null)
|
||
{
|
||
SetScroll(hScrollBar1, this.GraphPane.XAxis, _xScrollRange.Min, _xScrollRange.Max);
|
||
SetScroll(vScrollBar1, this.GraphPane.YAxis, _yScrollRangeList[0].Min,
|
||
_yScrollRangeList[0].Max);
|
||
}
|
||
|
||
SmoothingMode sModeSave = e.Graphics.SmoothingMode;
|
||
TextRenderingHint sHintSave = e.Graphics.TextRenderingHint;
|
||
if (_isAntiAlias)
|
||
{
|
||
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||
e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
|
||
}
|
||
base.OnPaint(e);
|
||
|
||
// Add a try/catch pair since the users of the control can't catch this one
|
||
try { _masterPane.Draw(e.Graphics); }
|
||
catch { }
|
||
|
||
e.Graphics.SmoothingMode = sModeSave;
|
||
e.Graphics.TextRenderingHint = sHintSave;
|
||
}
|
||
|
||
/*
|
||
// first, see if an old thread is still running
|
||
if ( t != null && t.IsAlive )
|
||
{
|
||
t.Abort();
|
||
}
|
||
|
||
//dt = new DrawingThread( e.Graphics, _masterPane );
|
||
//g = e.Graphics;
|
||
|
||
// Fire off the new thread
|
||
t = new Thread( new ParameterizedThreadStart( DoDrawingThread ) );
|
||
//ct.ApartmentState = ApartmentState.STA;
|
||
//ct.SetApartmentState( ApartmentState.STA );
|
||
DrawingThreadData dtd;
|
||
dtd._g = e.Graphics;
|
||
dtd._masterPane = _masterPane;
|
||
|
||
t.Start( dtd );
|
||
//ct.Join();
|
||
*/
|
||
}
|
||
|
||
// Thread t = null;
|
||
//DrawingThread dt = null;
|
||
|
||
/*
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="dtdobj"></param>
|
||
public void DoDrawingThread( object dtdobj )
|
||
{
|
||
try
|
||
{
|
||
DrawingThreadData dtd = (DrawingThreadData) dtdobj;
|
||
|
||
if ( dtd._g != null && dtd._masterPane != null )
|
||
dtd._masterPane.Draw( dtd._g );
|
||
|
||
// else
|
||
// {
|
||
// using ( Graphics g2 = CreateGraphics() )
|
||
// _masterPane.Draw( g2 );
|
||
// }
|
||
}
|
||
catch
|
||
{
|
||
|
||
}
|
||
}
|
||
*/
|
||
|
||
/// <summary>
|
||
/// Called when the control has been resized.
|
||
/// </summary>
|
||
/// <param name="sender">
|
||
/// A reference to the control that has been resized.
|
||
/// </param>
|
||
/// <param name="e">
|
||
/// An EventArgs object.
|
||
/// </param>
|
||
protected void ZedGraphControl_ReSize(object sender, System.EventArgs e)
|
||
{
|
||
lock (this)
|
||
{
|
||
if (BeenDisposed || _masterPane == null)
|
||
return;
|
||
|
||
Size newSize = this.Size;
|
||
|
||
if (_isShowHScrollBar)
|
||
{
|
||
hScrollBar1.Visible = true;
|
||
newSize.Height -= this.hScrollBar1.Size.Height;
|
||
hScrollBar1.Location = new Point(0, newSize.Height);
|
||
hScrollBar1.Size = new Size(newSize.Width, hScrollBar1.Height);
|
||
}
|
||
else
|
||
hScrollBar1.Visible = false;
|
||
|
||
if (_isShowVScrollBar)
|
||
{
|
||
vScrollBar1.Visible = true;
|
||
newSize.Width -= this.vScrollBar1.Size.Width;
|
||
vScrollBar1.Location = new Point(newSize.Width, 0);
|
||
vScrollBar1.Size = new Size(vScrollBar1.Width, newSize.Height);
|
||
}
|
||
else
|
||
vScrollBar1.Visible = false;
|
||
|
||
using (Graphics g = this.CreateGraphics())
|
||
{
|
||
_masterPane.ReSize(g, new RectangleF(0, 0, newSize.Width, newSize.Height));
|
||
//g.Dispose();
|
||
}
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
/// <summary>This performs an axis change command on the graphPane.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This is the same as
|
||
/// <c>ZedGraphControl.GraphPane.AxisChange( ZedGraphControl.CreateGraphics() )</c>, however,
|
||
/// this method also calls <see cref="SetScrollRangeFromData" /> if <see cref="IsAutoScrollRange" />
|
||
/// is true.
|
||
/// </remarks>
|
||
public virtual void AxisChange()
|
||
{
|
||
lock (this)
|
||
{
|
||
if (BeenDisposed || _masterPane == null)
|
||
return;
|
||
|
||
using (Graphics g = this.CreateGraphics())
|
||
{
|
||
_masterPane.AxisChange(g);
|
||
//g.Dispose();
|
||
}
|
||
|
||
if (_isAutoScrollRange)
|
||
SetScrollRangeFromData();
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region Mouse Events
|
||
|
||
/// <summary>
|
||
/// Handle a MouseDown event in the <see cref="ZedGraphControl" />
|
||
/// </summary>
|
||
/// <param name="sender">A reference to the <see cref="ZedGraphControl" /></param>
|
||
/// <param name="e">A <see cref="MouseEventArgs" /> instance</param>
|
||
protected void ZedGraphControl_MouseDown(object sender, MouseEventArgs e)
|
||
{
|
||
_isPanning = false;
|
||
_isZooming = false;
|
||
_isEditing = false;
|
||
_isSelecting = false;
|
||
_dragPane = null;
|
||
|
||
Point mousePt = new Point(e.X, e.Y);
|
||
|
||
// Callback for doubleclick events
|
||
if (_masterPane != null && e.Clicks > 1 && this.DoubleClickEvent != null)
|
||
{
|
||
if (this.DoubleClickEvent(this, e))
|
||
return;
|
||
}
|
||
|
||
// Provide Callback for MouseDown events
|
||
if (_masterPane != null && this.MouseDownEvent != null)
|
||
{
|
||
if (this.MouseDownEvent(this, e))
|
||
return;
|
||
}
|
||
|
||
if (e.Clicks > 1 || _masterPane == null)
|
||
return;
|
||
|
||
// First, see if the click is within a Linkable object within any GraphPane
|
||
GraphPane pane = this.MasterPane.FindPane(mousePt);
|
||
if (pane != null &&
|
||
e.Button == _linkButtons && Control.ModifierKeys == _linkModifierKeys)
|
||
{
|
||
object source;
|
||
Link link;
|
||
int index;
|
||
using (Graphics g = this.CreateGraphics())
|
||
{
|
||
float scaleFactor = pane.CalcScaleFactor();
|
||
if (pane.FindLinkableObject(mousePt, g, scaleFactor, out source, out link, out index))
|
||
{
|
||
if (LinkEvent != null && LinkEvent(this, pane, source, link, index))
|
||
return;
|
||
|
||
string url;
|
||
CurveItem curve = source as CurveItem;
|
||
|
||
if (curve != null)
|
||
url = link.MakeCurveItemUrl(pane, curve, index);
|
||
else
|
||
url = link._url;
|
||
|
||
if (url != string.Empty)
|
||
{
|
||
System.Diagnostics.Process.Start(url);
|
||
// linkable objects override any other actions with mouse
|
||
return;
|
||
}
|
||
}
|
||
//g.Dispose();
|
||
}
|
||
}
|
||
|
||
// Second, Check to see if it's within a Chart Rect
|
||
pane = this.MasterPane.FindChartRect(mousePt);
|
||
//Rectangle rect = new Rectangle( mousePt, new Size( 1, 1 ) );
|
||
|
||
if (pane != null &&
|
||
(_isEnableHPan || _isEnableVPan) &&
|
||
((e.Button == _panButtons && Control.ModifierKeys == _panModifierKeys) ||
|
||
(e.Button == _panButtons2 && Control.ModifierKeys == _panModifierKeys2)))
|
||
{
|
||
_isPanning = true;
|
||
_dragStartPt = mousePt;
|
||
_dragPane = pane;
|
||
//_zoomState = new ZoomState( _dragPane, ZoomState.StateType.Pan );
|
||
ZoomStateSave(_dragPane, ZoomState.StateType.Pan);
|
||
}
|
||
else if (pane != null && (_isEnableHZoom || _isEnableVZoom) &&
|
||
((e.Button == _zoomButtons && Control.ModifierKeys == _zoomModifierKeys) ||
|
||
(e.Button == _zoomButtons2 && Control.ModifierKeys == _zoomModifierKeys2)))
|
||
{
|
||
_isZooming = true;
|
||
_dragStartPt = mousePt;
|
||
_dragEndPt = mousePt;
|
||
_dragEndPt.Offset(1, 1);
|
||
_dragPane = pane;
|
||
ZoomStateSave(_dragPane, ZoomState.StateType.Zoom);
|
||
}
|
||
//Revision: JCarpenter 10/06
|
||
else if (pane != null && _isEnableSelection && e.Button == _selectButtons &&
|
||
(Control.ModifierKeys == _selectModifierKeys ||
|
||
Control.ModifierKeys == _selectAppendModifierKeys))
|
||
{
|
||
_isSelecting = true;
|
||
_dragStartPt = mousePt;
|
||
_dragEndPt = mousePt;
|
||
_dragEndPt.Offset(1, 1);
|
||
_dragPane = pane;
|
||
}
|
||
else if (pane != null && (_isEnableHEdit || _isEnableVEdit) &&
|
||
(e.Button == EditButtons && Control.ModifierKeys == EditModifierKeys))
|
||
{
|
||
|
||
// find the point that was clicked, and make sure the point list is editable
|
||
// and that it's a primary Y axis (the first Y or Y2 axis)
|
||
if (pane.FindNearestPoint(mousePt, out _dragCurve, out _dragIndex) &&
|
||
_dragCurve.Points is IPointListEdit)
|
||
{
|
||
_isEditing = true;
|
||
_dragPane = pane;
|
||
_dragStartPt = mousePt;
|
||
_dragStartPair = _dragCurve[_dragIndex];
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Set the cursor according to the current mouse location.
|
||
/// </summary>
|
||
protected void SetCursor()
|
||
{
|
||
SetCursor(this.PointToClient(Control.MousePosition));
|
||
}
|
||
|
||
/// <summary>
|
||
/// Set the cursor according to the current mouse location.
|
||
/// </summary>
|
||
protected void SetCursor(Point mousePt)
|
||
{
|
||
if (_masterPane != null)
|
||
{
|
||
GraphPane pane = _masterPane.FindChartRect(mousePt);
|
||
if ((_isEnableHPan || _isEnableVPan) && (Control.ModifierKeys == Keys.Shift || _isPanning) &&
|
||
(pane != null || _isPanning))
|
||
this.Cursor = Cursors.Hand;
|
||
else if ((_isEnableVZoom || _isEnableHZoom) && (pane != null || _isZooming))
|
||
this.Cursor = Cursors.Cross;
|
||
else if (_isEnableSelection && (pane != null || _isSelecting))
|
||
this.Cursor = Cursors.Cross;
|
||
else
|
||
this.Cursor = Cursors.Default;
|
||
|
||
// else if ( isZoomMode || isPanMode )
|
||
// this.Cursor = Cursors.No;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handle a KeyUp event
|
||
/// </summary>
|
||
/// <param name="sender">The <see cref="ZedGraphControl" /> in which the KeyUp occurred.</param>
|
||
/// <param name="e">A <see cref="KeyEventArgs" /> instance.</param>
|
||
protected void ZedGraphControl_KeyUp(object sender, KeyEventArgs e)
|
||
{
|
||
SetCursor();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handle the Key Events so ZedGraph can Escape out of a panning or zooming operation.
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
protected void ZedGraphControl_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
|
||
{
|
||
SetCursor();
|
||
|
||
if (e.KeyCode == Keys.Escape)
|
||
{
|
||
if (_isPanning)
|
||
HandlePanCancel();
|
||
if (_isZooming)
|
||
HandleZoomCancel();
|
||
if (_isEditing)
|
||
HandleEditCancel();
|
||
//if ( _isSelecting )
|
||
// Esc always cancels the selection
|
||
HandleSelectionCancel();
|
||
|
||
_isZooming = false;
|
||
_isPanning = false;
|
||
_isEditing = false;
|
||
_isSelecting = false;
|
||
|
||
Refresh();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handle a MouseUp event in the <see cref="ZedGraphControl" />
|
||
/// </summary>
|
||
/// <param name="sender">A reference to the <see cref="ZedGraphControl" /></param>
|
||
/// <param name="e">A <see cref="MouseEventArgs" /> instance</param>
|
||
protected void ZedGraphControl_MouseUp(object sender, MouseEventArgs e)
|
||
{
|
||
// Provide Callback for MouseUp events
|
||
if (_masterPane != null && this.MouseUpEvent != null)
|
||
{
|
||
if (this.MouseUpEvent(this, e))
|
||
return;
|
||
}
|
||
|
||
if (_masterPane != null && _dragPane != null)
|
||
{
|
||
// If the MouseUp event occurs, the user is done dragging.
|
||
if (_isZooming)
|
||
HandleZoomFinish(sender, e);
|
||
else if (_isPanning)
|
||
HandlePanFinish();
|
||
else if (_isEditing)
|
||
HandleEditFinish();
|
||
//Revision: JCarpenter 10/06
|
||
else if (_isSelecting)
|
||
HandleSelectionFinish(sender, e);
|
||
}
|
||
|
||
// Reset the rectangle.
|
||
//dragStartPt = new Rectangle( 0, 0, 0, 0 );
|
||
_dragPane = null;
|
||
_isZooming = false;
|
||
_isPanning = false;
|
||
_isEditing = false;
|
||
_isSelecting = false;
|
||
|
||
Cursor.Current = Cursors.Default;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Make a string label that corresponds to a user scale value.
|
||
/// </summary>
|
||
/// <param name="axis">The axis from which to obtain the scale value. This determines
|
||
/// if it's a date value, linear, log, etc.</param>
|
||
/// <param name="val">The value to be made into a label</param>
|
||
/// <param name="iPt">The ordinal position of the value</param>
|
||
/// <param name="isOverrideOrdinal">true to override the ordinal settings of the axis,
|
||
/// and prefer the actual value instead.</param>
|
||
/// <returns>The string label.</returns>
|
||
protected string MakeValueLabel(Axis axis, double val, int iPt, bool isOverrideOrdinal)
|
||
{
|
||
if (axis != null)
|
||
{
|
||
if (axis.Scale.IsDate || axis.Scale.Type == AxisType.DateAsOrdinal)
|
||
{
|
||
return XDate.ToString(val, _pointDateFormat);
|
||
}
|
||
else if (axis._scale.IsText && axis._scale._textLabels != null)
|
||
{
|
||
int i = iPt;
|
||
if (isOverrideOrdinal)
|
||
i = (int)(val - 0.5);
|
||
|
||
if (i >= 0 && i < axis._scale._textLabels.Length)
|
||
return axis._scale._textLabels[i];
|
||
else
|
||
return (i + 1).ToString();
|
||
}
|
||
else if (axis.Scale.IsAnyOrdinal && axis.Scale.Type != AxisType.LinearAsOrdinal
|
||
&& !isOverrideOrdinal)
|
||
{
|
||
return iPt.ToString(_pointValueFormat);
|
||
}
|
||
else
|
||
return val.ToString(_pointValueFormat);
|
||
}
|
||
else
|
||
return "";
|
||
}
|
||
|
||
/// <summary>
|
||
/// protected method for handling MouseMove events to display tooltips over
|
||
/// individual datapoints.
|
||
/// </summary>
|
||
/// <param name="sender">
|
||
/// A reference to the control that has the MouseMove event.
|
||
/// </param>
|
||
/// <param name="e">
|
||
/// A MouseEventArgs object.
|
||
/// </param>
|
||
protected void ZedGraphControl_MouseMove(object sender, MouseEventArgs e)
|
||
{
|
||
if (_masterPane != null)
|
||
{
|
||
// Provide Callback for MouseMove events
|
||
if (this.MouseMoveEvent != null && this.MouseMoveEvent(this, e))
|
||
return;
|
||
|
||
Point mousePt = new Point(e.X, e.Y);
|
||
|
||
//Point tempPt = this.PointToClient( Control.MousePosition );
|
||
|
||
SetCursor(mousePt);
|
||
|
||
// If the mouse is being dragged,
|
||
// undraw and redraw the rectangle as the mouse moves.
|
||
if (_isZooming)
|
||
HandleZoomDrag(mousePt);
|
||
else if (_isPanning)
|
||
HandlePanDrag(mousePt);
|
||
else if (_isEditing)
|
||
HandleEditDrag(mousePt);
|
||
else if (_isShowCursorValues)
|
||
HandleCursorValues(mousePt);
|
||
else if (_isShowPointValues)
|
||
HandlePointValues(mousePt);
|
||
//Revision: JCarpenter 10/06
|
||
else if (_isSelecting)
|
||
HandleZoomDrag(mousePt);
|
||
}
|
||
}
|
||
|
||
private Point HandlePointValues(Point mousePt)
|
||
{
|
||
int iPt;
|
||
GraphPane pane;
|
||
object nearestObj;
|
||
|
||
using (Graphics g = this.CreateGraphics())
|
||
{
|
||
|
||
if (_masterPane.FindNearestPaneObject(mousePt,
|
||
g, out pane, out nearestObj, out iPt))
|
||
{
|
||
if (nearestObj is CurveItem && iPt >= 0)
|
||
{
|
||
CurveItem curve = (CurveItem)nearestObj;
|
||
// Provide Callback for User to customize the tooltips
|
||
if (this.PointValueEvent != null)
|
||
{
|
||
string label = this.PointValueEvent(this, pane, curve, iPt);
|
||
if (label != null && label.Length > 0)
|
||
{
|
||
this.pointToolTip.SetToolTip(this, label);
|
||
this.pointToolTip.Active = true;
|
||
}
|
||
else
|
||
this.pointToolTip.Active = false;
|
||
}
|
||
else
|
||
{
|
||
|
||
if (curve is PieItem)
|
||
{
|
||
this.pointToolTip.SetToolTip(this,
|
||
((PieItem)curve).Value.ToString(_pointValueFormat));
|
||
}
|
||
// else if ( curve is OHLCBarItem || curve is JapaneseCandleStickItem )
|
||
// {
|
||
// StockPt spt = (StockPt)curve.Points[iPt];
|
||
// this.pointToolTip.SetToolTip( this, ( (XDate) spt.Date ).ToString( "MM/dd/yyyy" ) + "\nOpen: $" +
|
||
// spt.Open.ToString( "N2" ) +
|
||
// "\nHigh: $" +
|
||
// spt.High.ToString( "N2" ) + "\nLow: $" +
|
||
// spt.Low.ToString( "N2" ) + "\nClose: $" +
|
||
// spt.Close.ToString
|
||
// ( "N2" ) );
|
||
// }
|
||
else
|
||
{
|
||
PointPair pt = curve.Points[iPt];
|
||
|
||
if (pt.Tag is string)
|
||
this.pointToolTip.SetToolTip(this, (string)pt.Tag);
|
||
else
|
||
{
|
||
double xVal, yVal, lowVal;
|
||
ValueHandler valueHandler = new ValueHandler(pane, false);
|
||
if ((curve is BarItem || curve is ErrorBarItem || curve is HiLowBarItem)
|
||
&& pane.BarSettings.Base != BarBase.X)
|
||
valueHandler.GetValues(curve, iPt, out yVal, out lowVal, out xVal);
|
||
else
|
||
valueHandler.GetValues(curve, iPt, out xVal, out lowVal, out yVal);
|
||
|
||
string xStr = MakeValueLabel(curve.GetXAxis(pane), xVal, iPt,
|
||
curve.IsOverrideOrdinal);
|
||
string yStr = MakeValueLabel(curve.GetYAxis(pane), yVal, iPt,
|
||
curve.IsOverrideOrdinal);
|
||
|
||
this.pointToolTip.SetToolTip(this, "( " + xStr + ", " + yStr + " )");
|
||
|
||
//this.pointToolTip.SetToolTip( this,
|
||
// curve.Points[iPt].ToString( this.pointValueFormat ) );
|
||
}
|
||
}
|
||
|
||
this.pointToolTip.Active = true;
|
||
}
|
||
}
|
||
else
|
||
this.pointToolTip.Active = false;
|
||
}
|
||
else
|
||
this.pointToolTip.Active = false;
|
||
|
||
//g.Dispose();
|
||
}
|
||
return mousePt;
|
||
}
|
||
|
||
private Point HandleCursorValues(Point mousePt)
|
||
{
|
||
GraphPane pane = _masterPane.FindPane(mousePt);
|
||
if (pane != null && pane.Chart._rect.Contains(mousePt))
|
||
{
|
||
double x, x2, y, y2;
|
||
pane.ReverseTransform(mousePt, out x, out x2, out y, out y2);
|
||
string xStr = MakeValueLabel(pane.XAxis, x, -1, true);
|
||
string yStr = MakeValueLabel(pane.YAxis, y, -1, true);
|
||
string y2Str = MakeValueLabel(pane.Y2Axis, y2, -1, true);
|
||
|
||
this.pointToolTip.SetToolTip(this, "( " + xStr + ", " + yStr + ", " + y2Str + " )");
|
||
this.pointToolTip.Active = true;
|
||
}
|
||
else
|
||
this.pointToolTip.Active = false;
|
||
return mousePt;
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
#region Mouse Wheel Zoom Events
|
||
|
||
/// <summary>
|
||
/// Handle a MouseWheel event in the <see cref="ZedGraphControl" />
|
||
/// </summary>
|
||
/// <param name="sender">A reference to the <see cref="ZedGraphControl" /></param>
|
||
/// <param name="e">A <see cref="MouseEventArgs" /> instance</param>
|
||
protected void ZedGraphControl_MouseWheel(object sender, MouseEventArgs e)
|
||
{
|
||
if ((_isEnableVZoom || _isEnableHZoom) && _masterPane != null)
|
||
{
|
||
GraphPane pane = this.MasterPane.FindChartRect(new PointF(e.X, e.Y));
|
||
if (pane != null && e.Delta != 0)
|
||
{
|
||
ZoomState oldState = ZoomStateSave(pane, ZoomState.StateType.WheelZoom);
|
||
//ZoomState oldState = pane.ZoomStack.Push( pane, ZoomState.StateType.Zoom );
|
||
|
||
PointF centerPoint = new PointF(e.X, e.Y);
|
||
double zoomFraction = (1 + (e.Delta < 0 ? 1.0 : -1.0) * ZoomStepFraction);
|
||
|
||
ZoomPane(pane, zoomFraction, centerPoint, _isZoomOnMouseCenter, false);
|
||
|
||
ApplyToAllPanes(pane);
|
||
|
||
using (Graphics g = this.CreateGraphics())
|
||
{
|
||
// always AxisChange() the dragPane
|
||
pane.AxisChange(g);
|
||
|
||
foreach (GraphPane tempPane in _masterPane._paneList)
|
||
{
|
||
if (tempPane != pane && (_isSynchronizeXAxes || _isSynchronizeYAxes))
|
||
tempPane.AxisChange(g);
|
||
}
|
||
}
|
||
|
||
ZoomStatePush(pane);
|
||
|
||
// Provide Callback to notify the user of zoom events
|
||
if (this.ZoomEvent != null)
|
||
this.ZoomEvent(this, oldState, new ZoomState(pane, ZoomState.StateType.WheelZoom));
|
||
|
||
this.Refresh();
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Zoom a specified pane in or out according to the specified zoom fraction.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// The zoom will occur on the <see cref="XAxis" />, <see cref="YAxis" />, and
|
||
/// <see cref="Y2Axis" /> only if the corresponding flag, <see cref="IsEnableHZoom" /> or
|
||
/// <see cref="IsEnableVZoom" />, is true. Note that if there are multiple Y or Y2 axes, all of
|
||
/// them will be zoomed.
|
||
/// </remarks>
|
||
/// <param name="pane">The <see cref="GraphPane" /> instance to be zoomed.</param>
|
||
/// <param name="zoomFraction">The fraction by which to zoom, less than 1 to zoom in, greater than
|
||
/// 1 to zoom out. For example, 0.9 will zoom in such that the scale is 90% of what it was
|
||
/// originally.</param>
|
||
/// <param name="centerPt">The screen position about which the zoom will be centered. This
|
||
/// value is only used if <see paramref="isZoomOnCenter" /> is true.
|
||
/// </param>
|
||
/// <param name="isZoomOnCenter">true to cause the zoom to be centered on the point
|
||
/// <see paramref="centerPt" />, false to center on the <see cref="Chart.Rect" />.
|
||
/// </param>
|
||
/// <param name="isRefresh">true to force a refresh of the control, false to leave it unrefreshed</param>
|
||
protected void ZoomPane(GraphPane pane, double zoomFraction, PointF centerPt,
|
||
bool isZoomOnCenter, bool isRefresh)
|
||
{
|
||
double x;
|
||
double x2;
|
||
double[] y;
|
||
double[] y2;
|
||
|
||
pane.ReverseTransform(centerPt, out x, out x2, out y, out y2);
|
||
|
||
if (_isEnableHZoom)
|
||
{
|
||
ZoomScale(pane.XAxis, zoomFraction, x, isZoomOnCenter);
|
||
ZoomScale(pane.X2Axis, zoomFraction, x2, isZoomOnCenter);
|
||
}
|
||
if (_isEnableVZoom)
|
||
{
|
||
for (int i = 0; i < pane.YAxisList.Count; i++)
|
||
ZoomScale(pane.YAxisList[i], zoomFraction, y[i], isZoomOnCenter);
|
||
for (int i = 0; i < pane.Y2AxisList.Count; i++)
|
||
ZoomScale(pane.Y2AxisList[i], zoomFraction, y2[i], isZoomOnCenter);
|
||
}
|
||
|
||
using (Graphics g = this.CreateGraphics())
|
||
{
|
||
pane.AxisChange(g);
|
||
//g.Dispose();
|
||
}
|
||
|
||
this.SetScroll(this.hScrollBar1, pane.XAxis, _xScrollRange.Min, _xScrollRange.Max);
|
||
this.SetScroll(this.vScrollBar1, pane.YAxis, _yScrollRangeList[0].Min,
|
||
_yScrollRangeList[0].Max);
|
||
|
||
if (isRefresh)
|
||
Refresh();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Zoom a specified pane in or out according to the specified zoom fraction.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// The zoom will occur on the <see cref="XAxis" />, <see cref="YAxis" />, and
|
||
/// <see cref="Y2Axis" /> only if the corresponding flag, <see cref="IsEnableHZoom" /> or
|
||
/// <see cref="IsEnableVZoom" />, is true. Note that if there are multiple Y or Y2 axes, all of
|
||
/// them will be zoomed.
|
||
/// </remarks>
|
||
/// <param name="pane">The <see cref="GraphPane" /> instance to be zoomed.</param>
|
||
/// <param name="zoomFraction">The fraction by which to zoom, less than 1 to zoom in, greater than
|
||
/// 1 to zoom out. For example, 0.9 will zoom in such that the scale is 90% of what it was
|
||
/// originally.</param>
|
||
/// <param name="centerPt">The screen position about which the zoom will be centered. This
|
||
/// value is only used if <see paramref="isZoomOnCenter" /> is true.
|
||
/// </param>
|
||
/// <param name="isZoomOnCenter">true to cause the zoom to be centered on the point
|
||
/// <see paramref="centerPt" />, false to center on the <see cref="Chart.Rect" />.
|
||
/// </param>
|
||
public void ZoomPane(GraphPane pane, double zoomFraction, PointF centerPt, bool isZoomOnCenter)
|
||
{
|
||
ZoomPane(pane, zoomFraction, centerPt, isZoomOnCenter, true);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Zoom the specified axis by the specified amount, with the center of the zoom at the
|
||
/// (optionally) specified point.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This method is used for MouseWheel zoom operations</remarks>
|
||
/// <param name="axis">The <see cref="Axis" /> to be zoomed.</param>
|
||
/// <param name="zoomFraction">The zoom fraction, less than 1.0 to zoom in, greater than 1.0 to
|
||
/// zoom out. That is, a value of 0.9 will zoom in such that the scale length is 90% of what
|
||
/// it previously was.</param>
|
||
/// <param name="centerVal">The location for the center of the zoom. This is only used if
|
||
/// <see paramref="IsZoomOnMouseCenter" /> is true.</param>
|
||
/// <param name="isZoomOnCenter">true if the zoom is to be centered at the
|
||
/// <see paramref="centerVal" /> screen position, false for the zoom to be centered within
|
||
/// the <see cref="Chart.Rect" />.
|
||
/// </param>
|
||
protected void ZoomScale(Axis axis, double zoomFraction, double centerVal, bool isZoomOnCenter)
|
||
{
|
||
if (axis != null && zoomFraction > 0.0001 && zoomFraction < 1000.0)
|
||
{
|
||
Scale scale = axis._scale;
|
||
/*
|
||
if ( axis.Scale.IsLog )
|
||
{
|
||
double ratio = Math.Sqrt( axis._scale._max / axis._scale._min * zoomFraction );
|
||
|
||
if ( !isZoomOnCenter )
|
||
centerVal = Math.Sqrt( axis._scale._max * axis._scale._min );
|
||
|
||
axis._scale._min = centerVal / ratio;
|
||
axis._scale._max = centerVal * ratio;
|
||
}
|
||
else
|
||
{
|
||
*/
|
||
double minLin = axis._scale._minLinearized;
|
||
double maxLin = axis._scale._maxLinearized;
|
||
double range = (maxLin - minLin) * zoomFraction / 2.0;
|
||
|
||
if (!isZoomOnCenter)
|
||
centerVal = (maxLin + minLin) / 2.0;
|
||
|
||
axis._scale._minLinearized = centerVal - range;
|
||
axis._scale._maxLinearized = centerVal + range;
|
||
// }
|
||
|
||
axis._scale._minAuto = false;
|
||
axis._scale._maxAuto = false;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Pan Events
|
||
|
||
private Point HandlePanDrag(Point mousePt)
|
||
{
|
||
double x1, x2, xx1, xx2;
|
||
double[] y1, y2, yy1, yy2;
|
||
//PointF endPoint = mousePt;
|
||
//PointF startPoint = ( (Control)sender ).PointToClient( this.dragRect.Location );
|
||
|
||
_dragPane.ReverseTransform(_dragStartPt, out x1, out xx1, out y1, out yy1);
|
||
_dragPane.ReverseTransform(mousePt, out x2, out xx2, out y2, out yy2);
|
||
|
||
if (_isEnableHPan)
|
||
{
|
||
PanScale(_dragPane.XAxis, x1, x2);
|
||
PanScale(_dragPane.X2Axis, xx1, xx2);
|
||
this.SetScroll(this.hScrollBar1, _dragPane.XAxis, _xScrollRange.Min, _xScrollRange.Max);
|
||
}
|
||
if (_isEnableVPan)
|
||
{
|
||
for (int i = 0; i < y1.Length; i++)
|
||
PanScale(_dragPane.YAxisList[i], y1[i], y2[i]);
|
||
for (int i = 0; i < yy1.Length; i++)
|
||
PanScale(_dragPane.Y2AxisList[i], yy1[i], yy2[i]);
|
||
this.SetScroll(this.vScrollBar1, _dragPane.YAxis, _yScrollRangeList[0].Min,
|
||
_yScrollRangeList[0].Max);
|
||
}
|
||
|
||
ApplyToAllPanes(_dragPane);
|
||
|
||
Refresh();
|
||
|
||
_dragStartPt = mousePt;
|
||
|
||
return mousePt;
|
||
}
|
||
|
||
private void HandlePanFinish()
|
||
{
|
||
// push the prior saved zoomstate, since the scale ranges have already been changed on
|
||
// the fly during the panning operation
|
||
if (_zoomState != null && _zoomState.IsChanged(_dragPane))
|
||
{
|
||
//_dragPane.ZoomStack.Push( _zoomState );
|
||
ZoomStatePush(_dragPane);
|
||
|
||
// Provide Callback to notify the user of pan events
|
||
if (this.ZoomEvent != null)
|
||
this.ZoomEvent(this, _zoomState,
|
||
new ZoomState(_dragPane, ZoomState.StateType.Pan));
|
||
|
||
_zoomState = null;
|
||
}
|
||
}
|
||
|
||
private void HandlePanCancel()
|
||
{
|
||
if (_isPanning)
|
||
{
|
||
if (_zoomState != null && _zoomState.IsChanged(_dragPane))
|
||
{
|
||
ZoomStateRestore(_dragPane);
|
||
//_zoomState.ApplyState( _dragPane );
|
||
//_zoomState = null;
|
||
}
|
||
_isPanning = false;
|
||
Refresh();
|
||
|
||
ZoomStateClear();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handle a panning operation for the specified <see cref="Axis" />.
|
||
/// </summary>
|
||
/// <param name="axis">The <see cref="Axis" /> to be panned</param>
|
||
/// <param name="startVal">The value where the pan started. The scale range
|
||
/// will be shifted by the difference between <see paramref="startVal" /> and
|
||
/// <see paramref="endVal" />.
|
||
/// </param>
|
||
/// <param name="endVal">The value where the pan ended. The scale range
|
||
/// will be shifted by the difference between <see paramref="startVal" /> and
|
||
/// <see paramref="endVal" />.
|
||
/// </param>
|
||
protected void PanScale(Axis axis, double startVal, double endVal)
|
||
{
|
||
if (axis != null)
|
||
{
|
||
Scale scale = axis._scale;
|
||
double delta = scale.Linearize(startVal) - scale.Linearize(endVal);
|
||
|
||
scale._minLinearized += delta;
|
||
scale._maxLinearized += delta;
|
||
|
||
scale._minAuto = false;
|
||
scale._maxAuto = false;
|
||
|
||
/*
|
||
if ( axis.Type == AxisType.Log )
|
||
{
|
||
axis._scale._min *= startVal / endVal;
|
||
axis._scale._max *= startVal / endVal;
|
||
}
|
||
else
|
||
{
|
||
axis._scale._min += startVal - endVal;
|
||
axis._scale._max += startVal - endVal;
|
||
}
|
||
*/
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Edit Point Events
|
||
|
||
private void HandleEditDrag(Point mousePt)
|
||
{
|
||
// get the scale values that correspond to the current point
|
||
double curX, curY;
|
||
_dragPane.ReverseTransform(mousePt, _dragCurve.IsX2Axis, _dragCurve.IsY2Axis,
|
||
_dragCurve.YAxisIndex, out curX, out curY);
|
||
double startX, startY;
|
||
_dragPane.ReverseTransform(_dragStartPt, _dragCurve.IsX2Axis, _dragCurve.IsY2Axis,
|
||
_dragCurve.YAxisIndex, out startX, out startY);
|
||
|
||
// calculate the new scale values for the point
|
||
PointPair newPt = new PointPair(_dragStartPair);
|
||
|
||
Scale xScale = _dragCurve.GetXAxis(_dragPane)._scale;
|
||
if (_isEnableHEdit)
|
||
newPt.X = xScale.DeLinearize(xScale.Linearize(newPt.X) +
|
||
xScale.Linearize(curX) - xScale.Linearize(startX));
|
||
|
||
Scale yScale = _dragCurve.GetYAxis(_dragPane)._scale;
|
||
if (_isEnableVEdit)
|
||
newPt.Y = yScale.DeLinearize(yScale.Linearize(newPt.Y) +
|
||
yScale.Linearize(curY) - yScale.Linearize(startY));
|
||
|
||
// save the data back to the point list
|
||
IPointListEdit list = _dragCurve.Points as IPointListEdit;
|
||
if (list != null)
|
||
list[_dragIndex] = newPt;
|
||
|
||
// force a redraw
|
||
Refresh();
|
||
}
|
||
|
||
private void HandleEditFinish()
|
||
{
|
||
if (this.PointEditEvent != null)
|
||
this.PointEditEvent(this, _dragPane, _dragCurve, _dragIndex);
|
||
}
|
||
|
||
private void HandleEditCancel()
|
||
{
|
||
if (_isEditing)
|
||
{
|
||
IPointListEdit list = _dragCurve.Points as IPointListEdit;
|
||
if (list != null)
|
||
list[_dragIndex] = _dragStartPair;
|
||
_isEditing = false;
|
||
Refresh();
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Zoom Events
|
||
|
||
private void HandleZoomDrag(Point mousePt)
|
||
{
|
||
// Hide the previous rectangle by calling the
|
||
// DrawReversibleFrame method with the same parameters.
|
||
Rectangle rect = CalcScreenRect(_dragStartPt, _dragEndPt);
|
||
ControlPaint.DrawReversibleFrame(rect, this.BackColor, FrameStyle.Dashed);
|
||
|
||
// Bound the zoom to the ChartRect
|
||
_dragEndPt = Point.Round(BoundPointToRect(mousePt, _dragPane.Chart._rect));
|
||
rect = CalcScreenRect(_dragStartPt, _dragEndPt);
|
||
// Draw the new rectangle by calling DrawReversibleFrame again.
|
||
ControlPaint.DrawReversibleFrame(rect, this.BackColor, FrameStyle.Dashed);
|
||
}
|
||
|
||
private void HandleZoomFinish(object sender, MouseEventArgs e)
|
||
{
|
||
PointF mousePtF = BoundPointToRect(new Point(e.X, e.Y), _dragPane.Chart._rect);
|
||
|
||
// Only accept a drag if it covers at least 5 pixels in each direction
|
||
//Point curPt = ( (Control)sender ).PointToScreen( Point.Round( mousePt ) );
|
||
if ((Math.Abs(mousePtF.X - _dragStartPt.X) > 4 || !_isEnableHZoom) &&
|
||
(Math.Abs(mousePtF.Y - _dragStartPt.Y) > 4 || !_isEnableVZoom))
|
||
{
|
||
// Draw the rectangle to be evaluated. Set a dashed frame style
|
||
// using the FrameStyle enumeration.
|
||
//ControlPaint.DrawReversibleFrame( this.dragRect,
|
||
// this.BackColor, FrameStyle.Dashed );
|
||
|
||
double x1, x2, xx1, xx2;
|
||
double[] y1, y2, yy1, yy2;
|
||
//PointF startPoint = ( (Control)sender ).PointToClient( this.dragRect.Location );
|
||
|
||
_dragPane.ReverseTransform(_dragStartPt, out x1, out xx1, out y1, out yy1);
|
||
_dragPane.ReverseTransform(mousePtF, out x2, out xx2, out y2, out yy2);
|
||
|
||
ZoomStatePush(_dragPane);
|
||
//ZoomState oldState = _dragPane.ZoomStack.Push( _dragPane,
|
||
// ZoomState.StateType.Zoom );
|
||
|
||
if (_isEnableHZoom)
|
||
{
|
||
_dragPane.XAxis._scale._min = Math.Min(x1, x2);
|
||
_dragPane.XAxis._scale._minAuto = false;
|
||
_dragPane.XAxis._scale._max = Math.Max(x1, x2);
|
||
_dragPane.XAxis._scale._maxAuto = false;
|
||
|
||
_dragPane.X2Axis._scale._min = Math.Min(xx1, xx2);
|
||
_dragPane.X2Axis._scale._minAuto = false;
|
||
_dragPane.X2Axis._scale._max = Math.Max(xx1, xx2);
|
||
_dragPane.X2Axis._scale._maxAuto = false;
|
||
}
|
||
if (_isEnableVZoom)
|
||
{
|
||
for (int i = 0; i < y1.Length; i++)
|
||
{
|
||
_dragPane.YAxisList[i]._scale._min = Math.Min(y1[i], y2[i]);
|
||
_dragPane.YAxisList[i]._scale._max = Math.Max(y1[i], y2[i]);
|
||
_dragPane.YAxisList[i]._scale._minAuto = false;
|
||
_dragPane.YAxisList[i]._scale._maxAuto = false;
|
||
}
|
||
for (int i = 0; i < yy1.Length; i++)
|
||
{
|
||
_dragPane.Y2AxisList[i]._scale._min = Math.Min(yy1[i], yy2[i]);
|
||
_dragPane.Y2AxisList[i]._scale._max = Math.Max(yy1[i], yy2[i]);
|
||
_dragPane.Y2AxisList[i]._scale._minAuto = false;
|
||
_dragPane.Y2AxisList[i]._scale._maxAuto = false;
|
||
}
|
||
}
|
||
|
||
this.SetScroll(this.hScrollBar1, _dragPane.XAxis, _xScrollRange.Min, _xScrollRange.Max);
|
||
this.SetScroll(this.vScrollBar1, _dragPane.YAxis, _yScrollRangeList[0].Min,
|
||
_yScrollRangeList[0].Max);
|
||
|
||
ApplyToAllPanes(_dragPane);
|
||
|
||
// Provide Callback to notify the user of zoom events
|
||
if (this.ZoomEvent != null)
|
||
this.ZoomEvent(this, _zoomState, //oldState,
|
||
new ZoomState(_dragPane, ZoomState.StateType.Zoom));
|
||
|
||
using (Graphics g = this.CreateGraphics())
|
||
{
|
||
// always AxisChange() the dragPane
|
||
_dragPane.AxisChange(g);
|
||
|
||
foreach (GraphPane pane in _masterPane._paneList)
|
||
{
|
||
if (pane != _dragPane && (_isSynchronizeXAxes || _isSynchronizeYAxes))
|
||
pane.AxisChange(g);
|
||
}
|
||
}
|
||
}
|
||
|
||
Refresh();
|
||
}
|
||
|
||
private void HandleZoomCancel()
|
||
{
|
||
if (_isZooming)
|
||
{
|
||
_isZooming = false;
|
||
Refresh();
|
||
|
||
ZoomStateClear();
|
||
}
|
||
}
|
||
|
||
private PointF BoundPointToRect(Point mousePt, RectangleF rect)
|
||
{
|
||
PointF newPt = new PointF(mousePt.X, mousePt.Y);
|
||
|
||
if (mousePt.X < rect.X) newPt.X = rect.X;
|
||
if (mousePt.X > rect.Right) newPt.X = rect.Right;
|
||
if (mousePt.Y < rect.Y) newPt.Y = rect.Y;
|
||
if (mousePt.Y > rect.Bottom) newPt.Y = rect.Bottom;
|
||
|
||
return newPt;
|
||
}
|
||
|
||
private Rectangle CalcScreenRect(Point mousePt1, Point mousePt2)
|
||
{
|
||
Point screenPt = PointToScreen(mousePt1);
|
||
Size size = new Size(mousePt2.X - mousePt1.X, mousePt2.Y - mousePt1.Y);
|
||
Rectangle rect = new Rectangle(screenPt, size);
|
||
|
||
if (_isZooming)
|
||
{
|
||
Rectangle chartRect = Rectangle.Round(_dragPane.Chart._rect);
|
||
|
||
Point chartPt = PointToScreen(chartRect.Location);
|
||
|
||
if (!_isEnableVZoom)
|
||
{
|
||
rect.Y = chartPt.Y;
|
||
rect.Height = chartRect.Height + 1;
|
||
}
|
||
else if (!_isEnableHZoom)
|
||
{
|
||
rect.X = chartPt.X;
|
||
rect.Width = chartRect.Width + 1;
|
||
}
|
||
}
|
||
|
||
return rect;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Selection Events
|
||
|
||
// Revision: JCarpenter 10/06
|
||
/// <summary>
|
||
/// Perform selection on curves within the drag pane, or under the mouse click.
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void HandleSelectionFinish(object sender, MouseEventArgs e)
|
||
{
|
||
if (e.Button != _selectButtons)
|
||
{
|
||
Refresh();
|
||
return;
|
||
}
|
||
|
||
PointF mousePtF = BoundPointToRect(new Point(e.X, e.Y), _dragPane.Chart._rect);
|
||
|
||
PointF mousePt = BoundPointToRect(new Point(e.X, e.Y), _dragPane.Rect);
|
||
|
||
Point curPt = ((Control)sender).PointToScreen(Point.Round(mousePt));
|
||
|
||
// Only accept a drag if it covers at least 5 pixels in each direction
|
||
//Point curPt = ( (Control)sender ).PointToScreen( Point.Round( mousePt ) );
|
||
if ((Math.Abs(mousePtF.X - _dragStartPt.X) > 4) &&
|
||
(Math.Abs(mousePtF.Y - _dragStartPt.Y) > 4))
|
||
{
|
||
|
||
#region New Code to Select on Rubber Band
|
||
|
||
double x1, x2, xx1, xx2;
|
||
double[] y1, y2, yy1, yy2;
|
||
PointF startPoint = ((Control)sender).PointToClient(new Point(Convert.ToInt32(this._dragPane.Rect.X), Convert.ToInt32(this._dragPane.Rect.Y)));
|
||
|
||
_dragPane.ReverseTransform(_dragStartPt, out x1, out xx1, out y1, out yy1);
|
||
_dragPane.ReverseTransform(mousePtF, out x2, out xx2, out y2, out yy2);
|
||
|
||
CurveList objects = new CurveList();
|
||
|
||
double left = Math.Min(x1, x2);
|
||
double right = Math.Max(x1, x2);
|
||
|
||
double top = 0;
|
||
double bottom = 0;
|
||
|
||
for (int i = 0; i < y1.Length; i++)
|
||
{
|
||
bottom = Math.Min(y1[i], y2[i]);
|
||
top = Math.Max(y1[i], y2[i]);
|
||
}
|
||
|
||
for (int i = 0; i < yy1.Length; i++)
|
||
{
|
||
bottom = Math.Min(bottom, yy2[i]);
|
||
bottom = Math.Min(yy1[i], bottom);
|
||
top = Math.Max(top, yy2[i]);
|
||
top = Math.Max(yy1[i], top);
|
||
}
|
||
|
||
double w = right - left;
|
||
double h = bottom - top;
|
||
|
||
RectangleF rF = new RectangleF((float)left, (float)top, (float)w, (float)h);
|
||
|
||
_dragPane.FindContainedObjects(rF, this.CreateGraphics(), out objects);
|
||
|
||
if (Control.ModifierKeys == _selectAppendModifierKeys)
|
||
_selection.AddToSelection(_masterPane, objects);
|
||
else
|
||
_selection.Select(_masterPane, objects);
|
||
// this.Select( objects );
|
||
|
||
//Graphics g = this.CreateGraphics();
|
||
//this._dragPane.AxisChange( g );
|
||
//g.Dispose();
|
||
|
||
#endregion
|
||
}
|
||
else // It's a single-select
|
||
{
|
||
#region New Code to Single Select
|
||
|
||
//Point mousePt = new Point( e.X, e.Y );
|
||
|
||
int iPt;
|
||
GraphPane pane;
|
||
object nearestObj;
|
||
|
||
using (Graphics g = this.CreateGraphics())
|
||
{
|
||
if (this.MasterPane.FindNearestPaneObject(mousePt, g, out pane,
|
||
out nearestObj, out iPt))
|
||
{
|
||
if (nearestObj is CurveItem && iPt >= 0)
|
||
{
|
||
if (Control.ModifierKeys == _selectAppendModifierKeys)
|
||
_selection.AddToSelection(_masterPane, nearestObj as CurveItem);
|
||
else
|
||
_selection.Select(_masterPane, nearestObj as CurveItem);
|
||
}
|
||
else
|
||
_selection.ClearSelection(_masterPane);
|
||
|
||
Refresh();
|
||
}
|
||
else
|
||
{
|
||
_selection.ClearSelection(_masterPane);
|
||
}
|
||
}
|
||
#endregion New Code to Single Select
|
||
}
|
||
|
||
using (Graphics g = this.CreateGraphics())
|
||
{
|
||
// always AxisChange() the dragPane
|
||
_dragPane.AxisChange(g);
|
||
|
||
foreach (GraphPane pane in _masterPane._paneList)
|
||
{
|
||
if (pane != _dragPane && (_isSynchronizeXAxes || _isSynchronizeYAxes))
|
||
pane.AxisChange(g);
|
||
}
|
||
}
|
||
|
||
Refresh();
|
||
}
|
||
|
||
private void HandleSelectionCancel()
|
||
{
|
||
_isSelecting = false;
|
||
|
||
_selection.ClearSelection(_masterPane);
|
||
|
||
Refresh();
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region ScrollBars
|
||
|
||
private void vScrollBar1_Scroll(object sender, ScrollEventArgs e)
|
||
{
|
||
if (this.GraphPane != null)
|
||
{
|
||
/*
|
||
ScrollBar scrollBar = sender as ScrollBar;
|
||
bool clearZoomState = false;
|
||
//ZoomState curState = new ZoomState( this.GraphPane, ZoomState.StateType.Scroll );
|
||
if ( _zoomState == null ) //&& !scrollBar.Capture )
|
||
{
|
||
clearZoomState = true;
|
||
ZoomStateSave( this.GraphPane, ZoomState.StateType.Scroll );
|
||
}
|
||
*/
|
||
for (int i = 0; i < this.GraphPane.YAxisList.Count; i++)
|
||
{
|
||
ScrollRange scroll = _yScrollRangeList[i];
|
||
if (scroll.IsScrollable)
|
||
{
|
||
Axis axis = this.GraphPane.YAxisList[i];
|
||
HandleScroll(axis, e.NewValue, scroll.Min, scroll.Max, vScrollBar1.LargeChange,
|
||
!axis.Scale.IsReverse);
|
||
}
|
||
}
|
||
|
||
for (int i = 0; i < this.GraphPane.Y2AxisList.Count; i++)
|
||
{
|
||
ScrollRange scroll = _y2ScrollRangeList[i];
|
||
if (scroll.IsScrollable)
|
||
{
|
||
Axis axis = this.GraphPane.Y2AxisList[i];
|
||
HandleScroll(axis, e.NewValue, scroll.Min, scroll.Max, vScrollBar1.LargeChange,
|
||
!axis.Scale.IsReverse);
|
||
}
|
||
}
|
||
|
||
ApplyToAllPanes(this.GraphPane);
|
||
|
||
if (_zoomState != null) // && ! clearZoomState && scrollBar.Capture )
|
||
{
|
||
// Provide Callback to notify the user of scroll events
|
||
if (this.ScrollProgressEvent != null)
|
||
this.ScrollProgressEvent(this, vScrollBar1, _zoomState,
|
||
new ZoomState(this.GraphPane, ZoomState.StateType.Scroll));
|
||
}
|
||
/* else if ( clearZoomState && _zoomState != null && // !scrollBar.Capture &&
|
||
_zoomState.IsChanged( this.GraphPane ) )
|
||
{
|
||
//this.GraphPane.ZoomStack.Push( _zoomState );
|
||
ZoomStatePush( this.GraphPane );
|
||
|
||
// Provide Callback to notify the user of pan events
|
||
if ( this.ScrollDoneEvent != null )
|
||
this.ScrollDoneEvent( this, scrollBar, _zoomState,
|
||
new ZoomState( this.GraphPane, ZoomState.StateType.Scroll ) );
|
||
}
|
||
|
||
if ( clearZoomState )
|
||
_zoomState = null;
|
||
*/
|
||
}
|
||
}
|
||
|
||
private void ApplyToAllPanes(GraphPane primaryPane)
|
||
{
|
||
foreach (GraphPane pane in _masterPane._paneList)
|
||
{
|
||
if (pane != primaryPane)
|
||
{
|
||
if (_isSynchronizeXAxes)
|
||
Synchronize(primaryPane.XAxis, pane.XAxis);
|
||
if (_isSynchronizeYAxes)
|
||
Synchronize(primaryPane.YAxis, pane.YAxis);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void Synchronize(Axis source, Axis dest)
|
||
{
|
||
dest._scale._min = source._scale._min;
|
||
dest._scale._max = source._scale._max;
|
||
dest._scale._majorStep = source._scale._majorStep;
|
||
dest._scale._minorStep = source._scale._minorStep;
|
||
dest._scale._minAuto = source._scale._minAuto;
|
||
dest._scale._maxAuto = source._scale._maxAuto;
|
||
dest._scale._majorStepAuto = source._scale._majorStepAuto;
|
||
dest._scale._minorStepAuto = source._scale._minorStepAuto;
|
||
}
|
||
|
||
private void hScrollBar1_Scroll(object sender, ScrollEventArgs e)
|
||
{
|
||
if (this.GraphPane != null)
|
||
{
|
||
HandleScroll(this.GraphPane.XAxis, e.NewValue, _xScrollRange.Min, _xScrollRange.Max,
|
||
hScrollBar1.LargeChange, this.GraphPane.XAxis.Scale.IsReverse);
|
||
}
|
||
|
||
ApplyToAllPanes(this.GraphPane);
|
||
|
||
if (_zoomState != null && this.GraphPane != null)
|
||
{
|
||
// Provide Callback to notify the user of pan events
|
||
if (this.ScrollProgressEvent != null)
|
||
this.ScrollProgressEvent(this, hScrollBar1, _zoomState,
|
||
new ZoomState(this.GraphPane, ZoomState.StateType.Scroll));
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Use the MouseCaptureChanged as an indicator for the start and end of a scrolling operation
|
||
/// </summary>
|
||
private void ScrollBarMouseCaptureChanged(object sender, EventArgs e)
|
||
{
|
||
ScrollBar scrollBar = sender as ScrollBar;
|
||
if (scrollBar != null)
|
||
{
|
||
// If this is the start of a new scroll, then Capture will be true
|
||
if (scrollBar.Capture)
|
||
{
|
||
// save the original zoomstate
|
||
//_zoomState = new ZoomState( this.GraphPane, ZoomState.StateType.Scroll );
|
||
ZoomStateSave(this.GraphPane, ZoomState.StateType.Scroll);
|
||
}
|
||
else
|
||
{
|
||
// push the prior saved zoomstate, since the scale ranges have already been changed on
|
||
// the fly during the scrolling operation
|
||
if (_zoomState != null && _zoomState.IsChanged(this.GraphPane))
|
||
{
|
||
//this.GraphPane.ZoomStack.Push( _zoomState );
|
||
ZoomStatePush(this.GraphPane);
|
||
|
||
// Provide Callback to notify the user of pan events
|
||
if (this.ScrollDoneEvent != null)
|
||
this.ScrollDoneEvent(this, scrollBar, _zoomState,
|
||
new ZoomState(this.GraphPane, ZoomState.StateType.Scroll));
|
||
|
||
_zoomState = null;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private void HandleScroll(Axis axis, int newValue, double scrollMin, double scrollMax,
|
||
int largeChange, bool reverse)
|
||
{
|
||
if (axis != null)
|
||
{
|
||
if (scrollMin > axis._scale._min)
|
||
scrollMin = axis._scale._min;
|
||
if (scrollMax < axis._scale._max)
|
||
scrollMax = axis._scale._max;
|
||
|
||
int span = _ScrollControlSpan - largeChange;
|
||
if (span <= 0)
|
||
return;
|
||
|
||
if (reverse)
|
||
newValue = span - newValue;
|
||
|
||
Scale scale = axis._scale;
|
||
|
||
double delta = scale._maxLinearized - scale._minLinearized;
|
||
double scrollMin2 = scale.Linearize(scrollMax) - delta;
|
||
scrollMin = scale.Linearize(scrollMin);
|
||
//scrollMax = scale.Linearize( scrollMax );
|
||
double val = scrollMin + (double)newValue / (double)span *
|
||
(scrollMin2 - scrollMin);
|
||
scale._minLinearized = val;
|
||
scale._maxLinearized = val + delta;
|
||
/*
|
||
if ( axis.Scale.IsLog )
|
||
{
|
||
double ratio = axis._scale._max / axis._scale._min;
|
||
double scrollMin2 = scrollMax / ratio;
|
||
|
||
double val = scrollMin * Math.Exp( (double)newValue / (double)span *
|
||
( Math.Log( scrollMin2 ) - Math.Log( scrollMin ) ) );
|
||
axis._scale._min = val;
|
||
axis._scale._max = val * ratio;
|
||
}
|
||
else
|
||
{
|
||
double delta = axis._scale._max - axis._scale._min;
|
||
double scrollMin2 = scrollMax - delta;
|
||
|
||
double val = scrollMin + (double)newValue / (double)span *
|
||
( scrollMin2 - scrollMin );
|
||
axis._scale._min = val;
|
||
axis._scale._max = val + delta;
|
||
}
|
||
*/
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Sets the value of the scroll range properties (see <see cref="ScrollMinX" />,
|
||
/// <see cref="ScrollMaxX" />, <see cref="YScrollRangeList" />, and
|
||
/// <see cref="Y2ScrollRangeList" /> based on the actual range of the data for
|
||
/// each corresponding <see cref="Axis" />.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This method is called automatically by <see cref="AxisChange" /> if
|
||
/// <see cref="IsAutoScrollRange" />
|
||
/// is true. Note that this will not be called if you call AxisChange directly from the
|
||
/// <see cref="GraphPane" />. For example, zedGraphControl1.AxisChange() works properly, but
|
||
/// zedGraphControl1.GraphPane.AxisChange() does not.</remarks>
|
||
public void SetScrollRangeFromData()
|
||
{
|
||
if (this.GraphPane != null)
|
||
{
|
||
double grace = CalcScrollGrace(this.GraphPane.XAxis.Scale._rangeMin,
|
||
this.GraphPane.XAxis.Scale._rangeMax);
|
||
|
||
_xScrollRange.Min = this.GraphPane.XAxis.Scale._rangeMin - grace;
|
||
_xScrollRange.Max = this.GraphPane.XAxis.Scale._rangeMax + grace;
|
||
_xScrollRange.IsScrollable = true;
|
||
|
||
for (int i = 0; i < this.GraphPane.YAxisList.Count; i++)
|
||
{
|
||
Axis axis = this.GraphPane.YAxisList[i];
|
||
grace = CalcScrollGrace(axis.Scale._rangeMin, axis.Scale._rangeMax);
|
||
ScrollRange range = new ScrollRange(axis.Scale._rangeMin - grace,
|
||
axis.Scale._rangeMax + grace, _yScrollRangeList[i].IsScrollable);
|
||
|
||
if (i >= _yScrollRangeList.Count)
|
||
_yScrollRangeList.Add(range);
|
||
else
|
||
_yScrollRangeList[i] = range;
|
||
}
|
||
|
||
for (int i = 0; i < this.GraphPane.Y2AxisList.Count; i++)
|
||
{
|
||
Axis axis = this.GraphPane.Y2AxisList[i];
|
||
grace = CalcScrollGrace(axis.Scale._rangeMin, axis.Scale._rangeMax);
|
||
ScrollRange range = new ScrollRange(axis.Scale._rangeMin - grace,
|
||
axis.Scale._rangeMax + grace, _y2ScrollRangeList[i].IsScrollable);
|
||
|
||
if (i >= _y2ScrollRangeList.Count)
|
||
_y2ScrollRangeList.Add(range);
|
||
else
|
||
_y2ScrollRangeList[i] = range;
|
||
}
|
||
|
||
//this.GraphPane.CurveList.GetRange( out scrollMinX, out scrollMaxX,
|
||
// out scrollMinY, out scrollMaxY, out scrollMinY2, out scrollMaxY2, false, false,
|
||
// this.GraphPane );
|
||
}
|
||
}
|
||
|
||
private double CalcScrollGrace(double min, double max)
|
||
{
|
||
if (Math.Abs(max - min) < 1e-30)
|
||
{
|
||
if (Math.Abs(max) < 1e-30)
|
||
return _scrollGrace;
|
||
else
|
||
return max * _scrollGrace;
|
||
}
|
||
else
|
||
return (max - min) * _scrollGrace;
|
||
}
|
||
|
||
private void SetScroll(ScrollBar scrollBar, Axis axis, double scrollMin, double scrollMax)
|
||
{
|
||
if (scrollBar != null && axis != null)
|
||
{
|
||
scrollBar.Minimum = 0;
|
||
scrollBar.Maximum = _ScrollControlSpan - 1;
|
||
|
||
if (scrollMin > axis._scale._min)
|
||
scrollMin = axis._scale._min;
|
||
if (scrollMax < axis._scale._max)
|
||
scrollMax = axis._scale._max;
|
||
|
||
int val = 0;
|
||
|
||
Scale scale = axis._scale;
|
||
double minLinearized = scale._minLinearized;
|
||
double maxLinearized = scale._maxLinearized;
|
||
scrollMin = scale.Linearize(scrollMin);
|
||
scrollMax = scale.Linearize(scrollMax);
|
||
|
||
double scrollMin2 = scrollMax - (maxLinearized - minLinearized);
|
||
/*
|
||
if ( axis.Scale.IsLog )
|
||
scrollMin2 = scrollMax / ( axis._scale._max / axis._scale._min );
|
||
else
|
||
scrollMin2 = scrollMax - ( axis._scale._max - axis._scale._min );
|
||
*/
|
||
if (scrollMin >= scrollMin2)
|
||
{
|
||
//scrollBar.Visible = false;
|
||
scrollBar.Enabled = false;
|
||
scrollBar.Value = 0;
|
||
}
|
||
else
|
||
{
|
||
double ratio = (maxLinearized - minLinearized) / (scrollMax - scrollMin);
|
||
|
||
/*
|
||
if ( axis.Scale.IsLog )
|
||
ratio = ( Math.Log( axis._scale._max ) - Math.Log( axis._scale._min ) ) /
|
||
( Math.Log( scrollMax ) - Math.Log( scrollMin ) );
|
||
else
|
||
ratio = ( axis._scale._max - axis._scale._min ) / ( scrollMax - scrollMin );
|
||
*/
|
||
|
||
int largeChange = (int)(ratio * _ScrollControlSpan + 0.5);
|
||
if (largeChange < 1)
|
||
largeChange = 1;
|
||
scrollBar.LargeChange = largeChange;
|
||
|
||
int smallChange = largeChange / _ScrollSmallRatio;
|
||
if (smallChange < 1)
|
||
smallChange = 1;
|
||
scrollBar.SmallChange = smallChange;
|
||
|
||
int span = _ScrollControlSpan - largeChange;
|
||
|
||
val = (int)((minLinearized - scrollMin) / (scrollMin2 - scrollMin) *
|
||
span + 0.5);
|
||
/*
|
||
if ( axis.Scale.IsLog )
|
||
val = (int)( ( Math.Log( axis._scale._min ) - Math.Log( scrollMin ) ) /
|
||
( Math.Log( scrollMin2 ) - Math.Log( scrollMin ) ) * span + 0.5 );
|
||
else
|
||
val = (int)( ( axis._scale._min - scrollMin ) / ( scrollMin2 - scrollMin ) *
|
||
span + 0.5 );
|
||
*/
|
||
if (val < 0)
|
||
val = 0;
|
||
else if (val > span)
|
||
val = span;
|
||
|
||
//if ( ( axis is XAxis && axis.IsReverse ) || ( ( ! axis is XAxis ) && ! axis.IsReverse ) )
|
||
if ((axis is XAxis) == axis.Scale.IsReverse)
|
||
val = span - val;
|
||
|
||
if (val < scrollBar.Minimum)
|
||
val = scrollBar.Minimum;
|
||
if (val > scrollBar.Maximum)
|
||
val = scrollBar.Maximum;
|
||
|
||
scrollBar.Value = val;
|
||
scrollBar.Enabled = true;
|
||
//scrollBar.Visible = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region ContextMenu
|
||
|
||
// Revision: JCarpenter 10/06
|
||
/// <summary>
|
||
/// Public enumeration that specifies the type of
|
||
/// object present at the Context Menu's mouse location
|
||
/// </summary>
|
||
public enum ContextMenuObjectState
|
||
{
|
||
/// <summary>
|
||
/// The object is an Inactive Curve Item at the Context Menu's mouse position
|
||
/// </summary>
|
||
InactiveSelection,
|
||
/// <summary>
|
||
/// The object is an active Curve Item at the Context Menu's mouse position
|
||
/// </summary>
|
||
ActiveSelection,
|
||
/// <summary>
|
||
/// There is no selectable object present at the Context Menu's mouse position
|
||
/// </summary>
|
||
Background
|
||
}
|
||
|
||
//Revision: JCarpenter 10/06
|
||
/// <summary>
|
||
/// Find the object currently under the mouse cursor, and return its state.
|
||
/// </summary>
|
||
private ContextMenuObjectState GetObjectState()
|
||
{
|
||
ContextMenuObjectState objState = ContextMenuObjectState.Background;
|
||
|
||
// Determine object state
|
||
Point mousePt = this.PointToClient(Control.MousePosition);
|
||
int iPt;
|
||
GraphPane pane;
|
||
object nearestObj;
|
||
|
||
using (Graphics g = this.CreateGraphics())
|
||
{
|
||
if (this.MasterPane.FindNearestPaneObject(mousePt, g, out pane,
|
||
out nearestObj, out iPt))
|
||
{
|
||
CurveItem item = nearestObj as CurveItem;
|
||
|
||
if (item != null && iPt >= 0)
|
||
{
|
||
if (item.IsSelected)
|
||
objState = ContextMenuObjectState.ActiveSelection;
|
||
else
|
||
objState = ContextMenuObjectState.InactiveSelection;
|
||
}
|
||
}
|
||
}
|
||
|
||
return objState;
|
||
}
|
||
|
||
/// <summary>
|
||
/// protected method to handle the popup context menu in the <see cref="ZedGraphControl"/>.
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
|
||
{
|
||
// disable context menu by default
|
||
e.Cancel = true;
|
||
ContextMenuStrip menuStrip = sender as ContextMenuStrip;
|
||
|
||
//Revision: JCarpenter 10/06
|
||
ContextMenuObjectState objState = GetObjectState();
|
||
|
||
if (_masterPane != null && menuStrip != null)
|
||
{
|
||
menuStrip.Items.Clear();
|
||
|
||
_isZooming = false;
|
||
_isPanning = false;
|
||
Cursor.Current = Cursors.Default;
|
||
|
||
_menuClickPt = this.PointToClient(Control.MousePosition);
|
||
GraphPane pane = _masterPane.FindPane(_menuClickPt);
|
||
|
||
if (_isShowContextMenu)
|
||
{
|
||
string menuStr = string.Empty;
|
||
|
||
//ToolStripMenuItem item = new ToolStripMenuItem();
|
||
//item.Name = "copy";
|
||
//item.Tag = "copy";
|
||
//item.Text = _resourceManager.GetString( "copy" );
|
||
//item.Click += new System.EventHandler( this.MenuClick_Copy );
|
||
//menuStrip.Items.Add( item );
|
||
|
||
//ToolStripMenuItem item = new ToolStripMenuItem();
|
||
//item.Name = "<22><><EFBFBD><EFBFBD>ͼƬ";
|
||
//item.Tag = "<22><><EFBFBD><EFBFBD>ͼƬ";
|
||
//item.Text = _resourceManager.GetString("save_as");
|
||
//item.Click += new System.EventHandler(this.MenuClick_SaveAs);
|
||
//menuStrip.Items.Add(item);
|
||
|
||
//item = new ToolStripMenuItem();
|
||
//item.Name = "page_setup";
|
||
//item.Tag = "page_setup";
|
||
//item.Text = _resourceManager.GetString( "page_setup" );
|
||
//item.Click += new System.EventHandler( this.MenuClick_PageSetup );
|
||
//menuStrip.Items.Add( item );
|
||
|
||
//item = new ToolStripMenuItem();
|
||
//item.Name = "print";
|
||
//item.Tag = "print";
|
||
//item.Text = _resourceManager.GetString( "print" );
|
||
//item.Click += new System.EventHandler( this.MenuClick_Print );
|
||
//menuStrip.Items.Add( item );
|
||
|
||
//item = new ToolStripMenuItem();
|
||
//item.Name = "show_val";
|
||
//item.Tag = "show_val";
|
||
//item.Text = _resourceManager.GetString( "show_val" );
|
||
//item.Click += new System.EventHandler( this.MenuClick_ShowValues );
|
||
//item.Checked = this.IsShowPointValues;
|
||
//menuStrip.Items.Add( item );
|
||
|
||
//item = new ToolStripMenuItem();
|
||
//item.Name = "unzoom";
|
||
//item.Tag = "unzoom";
|
||
|
||
//if ( pane == null || pane.ZoomStack.IsEmpty )
|
||
// menuStr = _resourceManager.GetString( "unzoom" );
|
||
//else
|
||
//{
|
||
// switch ( pane.ZoomStack.Top.Type )
|
||
// {
|
||
// case ZoomState.StateType.Zoom:
|
||
// case ZoomState.StateType.WheelZoom:
|
||
// menuStr = _resourceManager.GetString( "unzoom" );
|
||
// break;
|
||
// case ZoomState.StateType.Pan:
|
||
// menuStr = _resourceManager.GetString( "unpan" );
|
||
// break;
|
||
// case ZoomState.StateType.Scroll:
|
||
// menuStr = _resourceManager.GetString( "unscroll" );
|
||
// break;
|
||
// }
|
||
//}
|
||
|
||
////menuItem.Text = "Un-" + ( ( pane == null || pane.zoomStack.IsEmpty ) ?
|
||
//// "Zoom" : pane.zoomStack.Top.TypeString );
|
||
//item.Text = menuStr;
|
||
//item.Click += new EventHandler( this.MenuClick_ZoomOut );
|
||
//if ( pane == null || pane.ZoomStack.IsEmpty )
|
||
// item.Enabled = false;
|
||
//menuStrip.Items.Add( item );
|
||
|
||
//item = new ToolStripMenuItem();
|
||
//item.Name = "undo_all";
|
||
//item.Tag = "undo_all";
|
||
//menuStr = _resourceManager.GetString( "undo_all" );
|
||
//item.Text = menuStr;
|
||
//item.Click += new EventHandler( this.MenuClick_ZoomOutAll );
|
||
//if ( pane == null || pane.ZoomStack.IsEmpty )
|
||
// item.Enabled = false;
|
||
//menuStrip.Items.Add( item );
|
||
|
||
//item = new ToolStripMenuItem();
|
||
//item.Name = "set_default";
|
||
//item.Tag = "set_default";
|
||
//menuStr = _resourceManager.GetString( "set_default" );
|
||
//item.Text = menuStr;
|
||
//item.Click += new EventHandler( this.MenuClick_RestoreScale );
|
||
//if ( pane == null )
|
||
// item.Enabled = false;
|
||
//menuStrip.Items.Add( item );
|
||
|
||
// if e.Cancel is set to false, the context menu does not display
|
||
// it is initially set to false because the context menu has no items
|
||
e.Cancel = false;
|
||
|
||
// Provide Callback for User to edit the context menu
|
||
//Revision: JCarpenter 10/06 - add ContextMenuObjectState objState
|
||
if (this.ContextMenuBuilder != null)
|
||
this.ContextMenuBuilder(this, menuStrip, _menuClickPt, objState);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handler for the "Copy" context menu item. Copies the current image to a bitmap on the
|
||
/// clipboard.
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
protected void MenuClick_Copy(System.Object sender, System.EventArgs e)
|
||
{
|
||
Copy(_isShowCopyMessage);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handler for the "Copy" context menu item. Copies the current image to a bitmap on the
|
||
/// clipboard.
|
||
/// </summary>
|
||
/// <param name="isShowMessage">boolean value that determines whether or not a prompt will be
|
||
/// displayed. true to show a message of "Image Copied to ClipBoard".</param>
|
||
public void Copy(bool isShowMessage)
|
||
{
|
||
if (_masterPane != null)
|
||
{
|
||
//Clipboard.SetDataObject( _masterPane.GetImage(), true );
|
||
|
||
// Threaded copy mode to avoid crash with MTA
|
||
// Contributed by Dave Moor
|
||
Thread ct = new Thread(new ThreadStart(this.ClipboardCopyThread));
|
||
//ct.ApartmentState = ApartmentState.STA;
|
||
ct.SetApartmentState(ApartmentState.STA);
|
||
ct.Start();
|
||
ct.Join();
|
||
|
||
if (isShowMessage)
|
||
{
|
||
string str = _resourceManager.GetString("copied_to_clip");
|
||
//MessageBox.Show( "Image Copied to ClipBoard" );
|
||
MessageBox.Show(str);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// A threaded version of the copy method to avoid crash with MTA
|
||
/// </summary>
|
||
private void ClipboardCopyThread()
|
||
{
|
||
Clipboard.SetDataObject(_masterPane.GetImage(), true);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handler for the "Save Image As" context menu item. Copies the current image to the selected
|
||
/// file.
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
protected void MenuClick_SaveAs(System.Object sender, System.EventArgs e)
|
||
{
|
||
SaveAs();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handler for the "Save Image As" context menu item. Copies the current image to the selected
|
||
/// file in either the Emf (vector), or a variety of Bitmap formats.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Note that <see cref="SaveAsBitmap" /> and <see cref="SaveAsEmf" /> methods are provided
|
||
/// which allow for Bitmap-only or Emf-only handling of the "Save As" context menu item.
|
||
/// </remarks>
|
||
public void SaveAs()
|
||
{
|
||
if (_masterPane != null)
|
||
{
|
||
_saveFileDialog.Filter =
|
||
"Emf Format (*.emf)|*.emf|" +
|
||
"PNG Format (*.png)|*.png|" +
|
||
"Gif Format (*.gif)|*.gif|" +
|
||
"Jpeg Format (*.jpg)|*.jpg|" +
|
||
"Tiff Format (*.tif)|*.tif|" +
|
||
"Bmp Format (*.bmp)|*.bmp";
|
||
|
||
if (_saveFileDialog.ShowDialog() == DialogResult.OK)
|
||
{
|
||
Stream myStream = _saveFileDialog.OpenFile();
|
||
if (myStream != null)
|
||
{
|
||
if (_saveFileDialog.FilterIndex == 1)
|
||
{
|
||
myStream.Close();
|
||
_masterPane.GetMetafile().Save(_saveFileDialog.FileName);
|
||
}
|
||
else
|
||
{
|
||
ImageFormat format = ImageFormat.Png;
|
||
if (_saveFileDialog.FilterIndex == 3)
|
||
format = ImageFormat.Gif;
|
||
else if (_saveFileDialog.FilterIndex == 4)
|
||
format = ImageFormat.Jpeg;
|
||
else if (_saveFileDialog.FilterIndex == 5)
|
||
format = ImageFormat.Tiff;
|
||
else if (_saveFileDialog.FilterIndex == 6)
|
||
format = ImageFormat.Bmp;
|
||
|
||
_masterPane.GetImage().Save(myStream, format);
|
||
myStream.Close();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handler for the "Save Image As" context menu item. Copies the current image to the selected
|
||
/// Bitmap file.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Note that this handler saves as a bitmap only. The default handler is
|
||
/// <see cref="SaveAs" />, which allows for Bitmap or EMF formats
|
||
/// </remarks>
|
||
public void SaveAsBitmap()
|
||
{
|
||
if (_masterPane != null)
|
||
{
|
||
_saveFileDialog.Filter =
|
||
"PNG Format (*.png)|*.png|" +
|
||
"Gif Format (*.gif)|*.gif|" +
|
||
"Jpeg Format (*.jpg)|*.jpg|" +
|
||
"Tiff Format (*.tif)|*.tif|" +
|
||
"Bmp Format (*.bmp)|*.bmp";
|
||
|
||
if (_saveFileDialog.ShowDialog() == DialogResult.OK)
|
||
{
|
||
ImageFormat format = ImageFormat.Png;
|
||
if (_saveFileDialog.FilterIndex == 2)
|
||
format = ImageFormat.Gif;
|
||
else if (_saveFileDialog.FilterIndex == 3)
|
||
format = ImageFormat.Jpeg;
|
||
else if (_saveFileDialog.FilterIndex == 4)
|
||
format = ImageFormat.Tiff;
|
||
else if (_saveFileDialog.FilterIndex == 5)
|
||
format = ImageFormat.Bmp;
|
||
|
||
Stream myStream = _saveFileDialog.OpenFile();
|
||
if (myStream != null)
|
||
{
|
||
_masterPane.GetImage().Save(myStream, format);
|
||
myStream.Close();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handler for the "Save Image As" context menu item. Copies the current image to the selected
|
||
/// Emf format file.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Note that this handler saves as an Emf format only. The default handler is
|
||
/// <see cref="SaveAs" />, which allows for Bitmap or EMF formats.
|
||
/// </remarks>
|
||
public void SaveAsEmf()
|
||
{
|
||
if (_masterPane != null)
|
||
{
|
||
_saveFileDialog.Filter = "Emf Format (*.emf)|*.emf";
|
||
|
||
if (_saveFileDialog.ShowDialog() == DialogResult.OK)
|
||
{
|
||
Stream myStream = _saveFileDialog.OpenFile();
|
||
if (myStream != null)
|
||
{
|
||
myStream.Close();
|
||
_masterPane.GetMetafile().Save(_saveFileDialog.FileName);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handler for the "Show Values" context menu item. Toggles the <see cref="IsShowPointValues"/>
|
||
/// property, which activates the point value tooltips.
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
protected void MenuClick_ShowValues(object sender, System.EventArgs e)
|
||
{
|
||
ToolStripMenuItem item = sender as ToolStripMenuItem;
|
||
if (item != null)
|
||
this.IsShowPointValues = !item.Checked;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handler for the "Set Scale to Default" context menu item. Sets the scale ranging to
|
||
/// full auto mode for all axes.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This method differs from the <see cref="ZoomOutAll" /> method in that it sets the scales
|
||
/// to full auto mode. The <see cref="ZoomOutAll" /> method sets the scales to their initial
|
||
/// setting prior to any user actions (which may or may not be full auto mode).
|
||
/// </remarks>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
protected void MenuClick_RestoreScale(object sender, EventArgs e)
|
||
{
|
||
if (_masterPane != null)
|
||
{
|
||
GraphPane pane = _masterPane.FindPane(_menuClickPt);
|
||
RestoreScale(pane);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handler for the "Set Scale to Default" context menu item. Sets the scale ranging to
|
||
/// full auto mode for all axes.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This method differs from the <see cref="ZoomOutAll" /> method in that it sets the scales
|
||
/// to full auto mode. The <see cref="ZoomOutAll" /> method sets the scales to their initial
|
||
/// setting prior to any user actions (which may or may not be full auto mode).
|
||
/// </remarks>
|
||
/// <param name="primaryPane">The <see cref="GraphPane" /> object which is to have the
|
||
/// scale restored</param>
|
||
public void RestoreScale(GraphPane primaryPane)
|
||
{
|
||
if (primaryPane != null)
|
||
{
|
||
//Go ahead and save the old zoomstates, which provides an "undo"-like capability
|
||
//ZoomState oldState = primaryPane.ZoomStack.Push( primaryPane, ZoomState.StateType.Zoom );
|
||
ZoomState oldState = new ZoomState(primaryPane, ZoomState.StateType.Zoom);
|
||
|
||
using (Graphics g = this.CreateGraphics())
|
||
{
|
||
if (_isSynchronizeXAxes || _isSynchronizeYAxes)
|
||
{
|
||
foreach (GraphPane pane in _masterPane._paneList)
|
||
{
|
||
pane.ZoomStack.Push(pane, ZoomState.StateType.Zoom);
|
||
ResetAutoScale(pane, g);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
primaryPane.ZoomStack.Push(primaryPane, ZoomState.StateType.Zoom);
|
||
ResetAutoScale(primaryPane, g);
|
||
}
|
||
|
||
// Provide Callback to notify the user of zoom events
|
||
if (this.ZoomEvent != null)
|
||
this.ZoomEvent(this, oldState, new ZoomState(primaryPane, ZoomState.StateType.Zoom));
|
||
|
||
//g.Dispose();
|
||
}
|
||
Refresh();
|
||
}
|
||
}
|
||
|
||
private void ResetAutoScale(GraphPane pane, Graphics g)
|
||
{
|
||
pane.XAxis.ResetAutoScale(pane, g);
|
||
pane.X2Axis.ResetAutoScale(pane, g);
|
||
foreach (YAxis axis in pane.YAxisList)
|
||
axis.ResetAutoScale(pane, g);
|
||
foreach (Y2Axis axis in pane.Y2AxisList)
|
||
axis.ResetAutoScale(pane, g);
|
||
}
|
||
|
||
/*
|
||
public void RestoreScale( GraphPane primaryPane )
|
||
{
|
||
if ( primaryPane != null )
|
||
{
|
||
Graphics g = this.CreateGraphics();
|
||
ZoomState oldState = new ZoomState( primaryPane, ZoomState.StateType.Zoom );
|
||
//ZoomState newState = null;
|
||
|
||
if ( _isSynchronizeXAxes || _isSynchronizeYAxes )
|
||
{
|
||
foreach ( GraphPane pane in _masterPane._paneList )
|
||
{
|
||
if ( pane == primaryPane )
|
||
{
|
||
pane.XAxis.ResetAutoScale( pane, g );
|
||
foreach ( YAxis axis in pane.YAxisList )
|
||
axis.ResetAutoScale( pane, g );
|
||
foreach ( Y2Axis axis in pane.Y2AxisList )
|
||
axis.ResetAutoScale( pane, g );
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
primaryPane.XAxis.ResetAutoScale( primaryPane, g );
|
||
foreach ( YAxis axis in primaryPane.YAxisList )
|
||
axis.ResetAutoScale( primaryPane, g );
|
||
foreach ( Y2Axis axis in primaryPane.Y2AxisList )
|
||
axis.ResetAutoScale( primaryPane, g );
|
||
}
|
||
|
||
// Provide Callback to notify the user of zoom events
|
||
if ( this.ZoomEvent != null )
|
||
this.ZoomEvent( this, oldState, new ZoomState( primaryPane, ZoomState.StateType.Zoom ) );
|
||
|
||
g.Dispose();
|
||
Refresh();
|
||
}
|
||
}
|
||
*/
|
||
/*
|
||
public void ZoomOutAll( GraphPane primaryPane )
|
||
{
|
||
if ( primaryPane != null && !primaryPane.ZoomStack.IsEmpty )
|
||
{
|
||
ZoomState.StateType type = primaryPane.ZoomStack.Top.Type;
|
||
|
||
ZoomState oldState = new ZoomState( primaryPane, type );
|
||
//ZoomState newState = pane.ZoomStack.PopAll( pane );
|
||
ZoomState newState = null;
|
||
if ( _isSynchronizeXAxes || _isSynchronizeYAxes )
|
||
{
|
||
foreach ( GraphPane pane in _masterPane._paneList )
|
||
{
|
||
ZoomState state = pane.ZoomStack.PopAll( pane );
|
||
if ( pane == primaryPane )
|
||
newState = state;
|
||
}
|
||
}
|
||
else
|
||
newState = primaryPane.ZoomStack.PopAll( primaryPane );
|
||
|
||
// Provide Callback to notify the user of zoom events
|
||
if ( this.ZoomEvent != null )
|
||
this.ZoomEvent( this, oldState, newState );
|
||
|
||
Refresh();
|
||
}
|
||
}
|
||
|
||
*/
|
||
|
||
/// <summary>
|
||
/// Handler for the "UnZoom/UnPan" context menu item. Restores the scale ranges to the values
|
||
/// before the last zoom or pan operation.
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
protected void MenuClick_ZoomOut(System.Object sender, System.EventArgs e)
|
||
{
|
||
if (_masterPane != null)
|
||
{
|
||
GraphPane pane = _masterPane.FindPane(_menuClickPt);
|
||
ZoomOut(pane);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handler for the "UnZoom/UnPan" context menu item. Restores the scale ranges to the values
|
||
/// before the last zoom, pan, or scroll operation.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Triggers a <see cref="ZoomEvent" /> for any type of undo (including pan, scroll, zoom, and
|
||
/// wheelzoom). This method will affect all the
|
||
/// <see cref="GraphPane" /> objects in the <see cref="MasterPane" /> if
|
||
/// <see cref="IsSynchronizeXAxes" /> or <see cref="IsSynchronizeYAxes" /> is true.
|
||
/// </remarks>
|
||
/// <param name="primaryPane">The primary <see cref="GraphPane" /> object which is to be
|
||
/// zoomed out</param>
|
||
public void ZoomOut(GraphPane primaryPane)
|
||
{
|
||
if (primaryPane != null && !primaryPane.ZoomStack.IsEmpty)
|
||
{
|
||
ZoomState.StateType type = primaryPane.ZoomStack.Top.Type;
|
||
|
||
ZoomState oldState = new ZoomState(primaryPane, type);
|
||
ZoomState newState = null;
|
||
if (_isSynchronizeXAxes || _isSynchronizeYAxes)
|
||
{
|
||
foreach (GraphPane pane in _masterPane._paneList)
|
||
{
|
||
ZoomState state = pane.ZoomStack.Pop(pane);
|
||
if (pane == primaryPane)
|
||
newState = state;
|
||
}
|
||
}
|
||
else
|
||
newState = primaryPane.ZoomStack.Pop(primaryPane);
|
||
|
||
// Provide Callback to notify the user of zoom events
|
||
if (this.ZoomEvent != null)
|
||
this.ZoomEvent(this, oldState, newState);
|
||
|
||
Refresh();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handler for the "Undo All Zoom/Pan" context menu item. Restores the scale ranges to the values
|
||
/// before all zoom and pan operations
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This method differs from the <see cref="RestoreScale" /> method in that it sets the scales
|
||
/// to their initial setting prior to any user actions. The <see cref="RestoreScale" /> method
|
||
/// sets the scales to full auto mode (regardless of what the initial setting may have been).
|
||
/// </remarks>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
protected void MenuClick_ZoomOutAll(System.Object sender, System.EventArgs e)
|
||
{
|
||
if (_masterPane != null)
|
||
{
|
||
GraphPane pane = _masterPane.FindPane(_menuClickPt);
|
||
ZoomOutAll(pane);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handler for the "Undo All Zoom/Pan" context menu item. Restores the scale ranges to the values
|
||
/// before all zoom and pan operations
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This method differs from the <see cref="RestoreScale" /> method in that it sets the scales
|
||
/// to their initial setting prior to any user actions. The <see cref="RestoreScale" /> method
|
||
/// sets the scales to full auto mode (regardless of what the initial setting may have been).
|
||
/// </remarks>
|
||
/// <param name="primaryPane">The <see cref="GraphPane" /> object which is to be zoomed out</param>
|
||
public void ZoomOutAll(GraphPane primaryPane)
|
||
{
|
||
if (primaryPane != null && !primaryPane.ZoomStack.IsEmpty)
|
||
{
|
||
ZoomState.StateType type = primaryPane.ZoomStack.Top.Type;
|
||
|
||
ZoomState oldState = new ZoomState(primaryPane, type);
|
||
//ZoomState newState = pane.ZoomStack.PopAll( pane );
|
||
ZoomState newState = null;
|
||
if (_isSynchronizeXAxes || _isSynchronizeYAxes)
|
||
{
|
||
foreach (GraphPane pane in _masterPane._paneList)
|
||
{
|
||
ZoomState state = pane.ZoomStack.PopAll(pane);
|
||
if (pane == primaryPane)
|
||
newState = state;
|
||
}
|
||
}
|
||
else
|
||
newState = primaryPane.ZoomStack.PopAll(primaryPane);
|
||
|
||
// Provide Callback to notify the user of zoom events
|
||
if (this.ZoomEvent != null)
|
||
this.ZoomEvent(this, oldState, newState);
|
||
|
||
Refresh();
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Printing
|
||
|
||
/// <summary>
|
||
/// Handler for the "Page Setup..." context menu item. Displays a
|
||
/// <see cref="PageSetupDialog" />.
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
protected void MenuClick_PageSetup(object sender, EventArgs e)
|
||
{
|
||
DoPageSetup();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handler for the "Print..." context menu item. Displays a
|
||
/// <see cref="PrintDialog" />.
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
protected void MenuClick_Print(object sender, EventArgs e)
|
||
{
|
||
DoPrint();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Rendering method used by the print context menu items
|
||
/// </summary>
|
||
/// <param name="sender">The applicable <see cref="PrintDocument" />.</param>
|
||
/// <param name="e">A <see cref="PrintPageEventArgs" /> instance providing
|
||
/// page bounds, margins, and a Graphics instance for this printed output.
|
||
/// </param>
|
||
private void Graph_PrintPage(object sender, PrintPageEventArgs e)
|
||
{
|
||
PrintDocument pd = sender as PrintDocument;
|
||
|
||
MasterPane mPane = this.MasterPane;
|
||
bool[] isPenSave = new bool[mPane.PaneList.Count + 1];
|
||
bool[] isFontSave = new bool[mPane.PaneList.Count + 1];
|
||
isPenSave[0] = mPane.IsPenWidthScaled;
|
||
isFontSave[0] = mPane.IsFontsScaled;
|
||
for (int i = 0; i < mPane.PaneList.Count; i++)
|
||
{
|
||
isPenSave[i + 1] = mPane[i].IsPenWidthScaled;
|
||
isFontSave[i + 1] = mPane[i].IsFontsScaled;
|
||
if (_isPrintScaleAll)
|
||
{
|
||
mPane[i].IsPenWidthScaled = true;
|
||
mPane[i].IsFontsScaled = true;
|
||
}
|
||
}
|
||
|
||
RectangleF saveRect = mPane.Rect;
|
||
SizeF newSize = mPane.Rect.Size;
|
||
if (_isPrintFillPage && _isPrintKeepAspectRatio)
|
||
{
|
||
float xRatio = (float)e.MarginBounds.Width / (float)newSize.Width;
|
||
float yRatio = (float)e.MarginBounds.Height / (float)newSize.Height;
|
||
float ratio = Math.Min(xRatio, yRatio);
|
||
|
||
newSize.Width *= ratio;
|
||
newSize.Height *= ratio;
|
||
}
|
||
else if (_isPrintFillPage)
|
||
newSize = e.MarginBounds.Size;
|
||
|
||
mPane.ReSize(e.Graphics, new RectangleF(e.MarginBounds.Left,
|
||
e.MarginBounds.Top, newSize.Width, newSize.Height));
|
||
mPane.Draw(e.Graphics);
|
||
|
||
using (Graphics g = this.CreateGraphics())
|
||
{
|
||
mPane.ReSize(g, saveRect);
|
||
//g.Dispose();
|
||
}
|
||
|
||
mPane.IsPenWidthScaled = isPenSave[0];
|
||
mPane.IsFontsScaled = isFontSave[0];
|
||
for (int i = 0; i < mPane.PaneList.Count; i++)
|
||
{
|
||
mPane[i].IsPenWidthScaled = isPenSave[i + 1];
|
||
mPane[i].IsFontsScaled = isFontSave[i + 1];
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the <see cref="System.Drawing.Printing.PrintDocument" /> instance
|
||
/// that is used for all of the context menu printing functions.
|
||
/// </summary>
|
||
public PrintDocument PrintDocument
|
||
{
|
||
get
|
||
{
|
||
// Add a try/catch pair since the users of the control can't catch this one
|
||
try
|
||
{
|
||
if (_pdSave == null)
|
||
{
|
||
_pdSave = new PrintDocument();
|
||
_pdSave.PrintPage += new PrintPageEventHandler(Graph_PrintPage);
|
||
}
|
||
}
|
||
catch (Exception exception)
|
||
{
|
||
MessageBox.Show(exception.Message);
|
||
}
|
||
|
||
return _pdSave;
|
||
}
|
||
set { _pdSave = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Display a <see cref="PageSetupDialog" /> to the user, allowing them to modify
|
||
/// the print settings for this <see cref="ZedGraphControl" />.
|
||
/// </summary>
|
||
public void DoPageSetup()
|
||
{
|
||
PrintDocument pd = PrintDocument;
|
||
|
||
// Add a try/catch pair since the users of the control can't catch this one
|
||
try
|
||
{
|
||
if (pd != null)
|
||
{
|
||
//pd.PrintPage += new PrintPageEventHandler( GraphPrintPage );
|
||
PageSetupDialog setupDlg = new PageSetupDialog();
|
||
setupDlg.Document = pd;
|
||
|
||
if (setupDlg.ShowDialog() == DialogResult.OK)
|
||
{
|
||
pd.PrinterSettings = setupDlg.PrinterSettings;
|
||
pd.DefaultPageSettings = setupDlg.PageSettings;
|
||
|
||
// BUG in PrintDocument!!! Converts in/mm repeatedly
|
||
// http://support.microsoft.com/?id=814355
|
||
// from http://www.vbinfozine.com/tpagesetupdialog.shtml, by Palo Mraz
|
||
//if ( System.Globalization.RegionInfo.CurrentRegion.IsMetric )
|
||
//{
|
||
// setupDlg.Document.DefaultPageSettings.Margins = PrinterUnitConvert.Convert(
|
||
// setupDlg.Document.DefaultPageSettings.Margins,
|
||
// PrinterUnit.Display, PrinterUnit.TenthsOfAMillimeter );
|
||
//}
|
||
}
|
||
}
|
||
}
|
||
|
||
catch (Exception exception)
|
||
{
|
||
MessageBox.Show(exception.Message);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Display a <see cref="PrintDialog" /> to the user, allowing them to select a
|
||
/// printer and print the <see cref="MasterPane" /> contained in this
|
||
/// <see cref="ZedGraphControl" />.
|
||
/// </summary>
|
||
public void DoPrint()
|
||
{
|
||
// Add a try/catch pair since the users of the control can't catch this one
|
||
try
|
||
{
|
||
PrintDocument pd = PrintDocument;
|
||
|
||
if (pd != null)
|
||
{
|
||
//pd.PrintPage += new PrintPageEventHandler( Graph_PrintPage );
|
||
PrintDialog pDlg = new PrintDialog();
|
||
pDlg.Document = pd;
|
||
if (pDlg.ShowDialog() == DialogResult.OK)
|
||
pd.Print();
|
||
}
|
||
}
|
||
catch (Exception exception)
|
||
{
|
||
MessageBox.Show(exception.Message);
|
||
}
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// Display a <see cref="PrintPreviewDialog" />, allowing the user to preview and
|
||
/// subsequently print the <see cref="MasterPane" /> contained in this
|
||
/// <see cref="ZedGraphControl" />.
|
||
/// </summary>
|
||
public void DoPrintPreview()
|
||
{
|
||
// Add a try/catch pair since the users of the control can't catch this one
|
||
try
|
||
{
|
||
PrintDocument pd = PrintDocument;
|
||
|
||
if (pd != null)
|
||
{
|
||
PrintPreviewDialog ppd = new PrintPreviewDialog();
|
||
//pd.PrintPage += new PrintPageEventHandler( Graph_PrintPage );
|
||
ppd.Document = pd;
|
||
ppd.Show(this);
|
||
}
|
||
}
|
||
catch (Exception exception)
|
||
{
|
||
MessageBox.Show(exception.Message);
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Zoom States
|
||
|
||
/// <summary>
|
||
/// Save the current states of the GraphPanes to a separate collection. Save a single
|
||
/// (<see paramref="primaryPane" />) GraphPane if the panes are not synchronized
|
||
/// (see <see cref="IsSynchronizeXAxes" /> and <see cref="IsSynchronizeYAxes" />),
|
||
/// or save a list of states for all GraphPanes if the panes are synchronized.
|
||
/// </summary>
|
||
/// <param name="primaryPane">The primary GraphPane on which zoom/pan/scroll operations
|
||
/// are taking place</param>
|
||
/// <param name="type">The <see cref="ZoomState.StateType" /> that describes the
|
||
/// current operation</param>
|
||
/// <returns>The <see cref="ZoomState" /> that corresponds to the
|
||
/// <see paramref="primaryPane" />.
|
||
/// </returns>
|
||
private ZoomState ZoomStateSave(GraphPane primaryPane, ZoomState.StateType type)
|
||
{
|
||
ZoomStateClear();
|
||
|
||
if (_isSynchronizeXAxes || _isSynchronizeYAxes)
|
||
{
|
||
foreach (GraphPane pane in _masterPane._paneList)
|
||
{
|
||
ZoomState state = new ZoomState(pane, type);
|
||
if (pane == primaryPane)
|
||
_zoomState = state;
|
||
_zoomStateStack.Add(state);
|
||
}
|
||
}
|
||
else
|
||
_zoomState = new ZoomState(primaryPane, type);
|
||
|
||
return _zoomState;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Restore the states of the GraphPanes to a previously saved condition (via
|
||
/// <see cref="ZoomStateSave" />. This is essentially an "undo" for live
|
||
/// pan and scroll actions. Restores a single
|
||
/// (<see paramref="primaryPane" />) GraphPane if the panes are not synchronized
|
||
/// (see <see cref="IsSynchronizeXAxes" /> and <see cref="IsSynchronizeYAxes" />),
|
||
/// or save a list of states for all GraphPanes if the panes are synchronized.
|
||
/// </summary>
|
||
/// <param name="primaryPane">The primary GraphPane on which zoom/pan/scroll operations
|
||
/// are taking place</param>
|
||
private void ZoomStateRestore(GraphPane primaryPane)
|
||
{
|
||
if (_isSynchronizeXAxes || _isSynchronizeYAxes)
|
||
{
|
||
for (int i = 0; i < _masterPane._paneList.Count; i++)
|
||
{
|
||
if (i < _zoomStateStack.Count)
|
||
_zoomStateStack[i].ApplyState(_masterPane._paneList[i]);
|
||
}
|
||
}
|
||
else if (_zoomState != null)
|
||
_zoomState.ApplyState(primaryPane);
|
||
|
||
ZoomStateClear();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Place the previously saved states of the GraphPanes on the individual GraphPane
|
||
/// <see cref="ZedGraph.GraphPane.ZoomStack" /> collections. This provides for an
|
||
/// option to undo the state change at a later time. Save a single
|
||
/// (<see paramref="primaryPane" />) GraphPane if the panes are not synchronized
|
||
/// (see <see cref="IsSynchronizeXAxes" /> and <see cref="IsSynchronizeYAxes" />),
|
||
/// or save a list of states for all GraphPanes if the panes are synchronized.
|
||
/// </summary>
|
||
/// <param name="primaryPane">The primary GraphPane on which zoom/pan/scroll operations
|
||
/// are taking place</param>
|
||
/// <returns>The <see cref="ZoomState" /> that corresponds to the
|
||
/// <see paramref="primaryPane" />.
|
||
/// </returns>
|
||
private void ZoomStatePush(GraphPane primaryPane)
|
||
{
|
||
if (_isSynchronizeXAxes || _isSynchronizeYAxes)
|
||
{
|
||
for (int i = 0; i < _masterPane._paneList.Count; i++)
|
||
{
|
||
if (i < _zoomStateStack.Count)
|
||
_masterPane._paneList[i].ZoomStack.Add(_zoomStateStack[i]);
|
||
}
|
||
}
|
||
else if (_zoomState != null)
|
||
primaryPane.ZoomStack.Add(_zoomState);
|
||
|
||
ZoomStateClear();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Clear the collection of saved states.
|
||
/// </summary>
|
||
private void ZoomStateClear()
|
||
{
|
||
_zoomStateStack.Clear();
|
||
_zoomState = null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Clear all states from the undo stack for each GraphPane.
|
||
/// </summary>
|
||
private void ZoomStatePurge()
|
||
{
|
||
foreach (GraphPane pane in _masterPane._paneList)
|
||
pane.ZoomStack.Clear();
|
||
}
|
||
|
||
#endregion
|
||
|
||
}
|
||
}
|