1441 lines
52 KiB
C#
1441 lines
52 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.Drawing;
|
|
using System.Drawing.Drawing2D;
|
|
using System.Runtime.Serialization;
|
|
using System.Security.Permissions;
|
|
|
|
namespace DrawGraph
|
|
{
|
|
/// <summary>
|
|
/// The Axis class is an abstract base class that encompasses all properties
|
|
/// and methods required to define a graph Axis.
|
|
/// </summary>
|
|
/// <remarks>This class is inherited by the
|
|
/// <see cref="XAxis"/>, <see cref="YAxis"/>, and <see cref="Y2Axis"/> classes
|
|
/// to define specific characteristics for those types.
|
|
/// </remarks>
|
|
///
|
|
/// <author> John Champion modified by Jerry Vos </author>
|
|
/// <version> $Revision: 3.73 $ $Date: 2007/05/19 06:06:05 $ </version>
|
|
[Serializable]
|
|
abstract public class Axis : ISerializable, ICloneable
|
|
{
|
|
|
|
#region Class Fields
|
|
|
|
/// <summary>
|
|
/// private field that stores the <see cref="ZedGraph.Scale" /> class, which implements all the
|
|
/// calculations and methods associated with the numeric scale for this
|
|
/// <see cref="Axis" />. See the public property <see cref="Scale" /> to access this class.
|
|
/// </summary>
|
|
internal Scale _scale;
|
|
|
|
/// <summary>
|
|
/// Private field that stores the <see cref="ZedGraph.MinorTic" /> class, which handles all
|
|
/// the minor tic information. See the public property <see cref="MinorTic" /> to access this class.
|
|
/// </summary>
|
|
internal MinorTic _minorTic;
|
|
/// <summary>
|
|
/// Private field that stores the <see cref="ZedGraph.MajorTic" /> class, which handles all
|
|
/// the major tic information. See the public property <see cref="MajorTic" /> to access this class.
|
|
/// </summary>
|
|
internal MajorTic _majorTic;
|
|
|
|
/// <summary>
|
|
/// Private field that stores the <see cref="ZedGraph.MajorGrid" /> class, which handles all
|
|
/// the major grid information. See the public property <see cref="MajorGrid" /> to access this class.
|
|
/// </summary>
|
|
internal MajorGrid _majorGrid;
|
|
/// <summary>
|
|
/// Private field that stores the <see cref="ZedGraph.MinorGrid" /> class, which handles all
|
|
/// the minor grid information. See the public property <see cref="MinorGrid" /> to access this class.
|
|
/// </summary>
|
|
internal MinorGrid _minorGrid;
|
|
|
|
/// <summary> Private fields for the <see cref="Axis"/> scale rendering properties.
|
|
/// Use the public properties <see cref="Cross"/> and <see cref="ZedGraph.Scale.BaseTic"/>
|
|
/// for access to these values.
|
|
/// </summary>
|
|
internal double _cross;
|
|
|
|
/// <summary> Private field for the <see cref="Axis"/> automatic cross position mode.
|
|
/// Use the public property <see cref="CrossAuto"/> for access to this value.
|
|
/// </summary>
|
|
internal bool _crossAuto;
|
|
|
|
/// <summary> Private fields for the <see cref="Axis"/> attributes.
|
|
/// Use the public properties <see cref="IsVisible"/>, <see cref="IsAxisSegmentVisible"/>
|
|
/// for access to these values.
|
|
/// </summary>
|
|
protected bool _isVisible,
|
|
_isAxisSegmentVisible;
|
|
|
|
/// <summary> Private field for the <see cref="Axis"/> title string.
|
|
/// Use the public property <see cref="Title"/> for access to this value.
|
|
/// </summary>
|
|
protected AxisLabel _title;
|
|
|
|
/// <summary>
|
|
/// A tag object for use by the user. This can be used to store additional
|
|
/// information associated with the <see cref="Axis"/>. ZedGraph does
|
|
/// not use this value for any purpose.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Note that, if you are going to Serialize ZedGraph data, then any type
|
|
/// that you store in <see cref="Tag"/> must be a serializable type (or
|
|
/// it will cause an exception).
|
|
/// </remarks>
|
|
public object Tag;
|
|
|
|
/// <summary> Private field for the <see cref="Axis"/> drawing dimensions.
|
|
/// Use the public property <see cref="AxisGap"/>
|
|
/// for access to these values. </summary>
|
|
private float _axisGap;
|
|
|
|
/// <summary>
|
|
/// Private field for the <see cref="Axis"/> minimum allowable space allocation.
|
|
/// Use the public property <see cref="MinSpace"/> to access this value.
|
|
/// </summary>
|
|
/// <seealso cref="Default.MinSpace"/>
|
|
private float _minSpace;
|
|
|
|
/// <summary> Private fields for the <see cref="Axis"/> colors.
|
|
/// Use the public property <see cref="Color"/> for access to this values.
|
|
/// </summary>
|
|
private Color _color;
|
|
|
|
/// <summary>
|
|
/// Temporary values for axis space calculations (see <see cref="CalcSpace" />).
|
|
/// </summary>
|
|
internal float _tmpSpace;
|
|
|
|
#endregion
|
|
|
|
#region Events
|
|
|
|
/// <summary>
|
|
/// A delegate that allows full custom formatting of the Axis labels
|
|
/// </summary>
|
|
/// <param name="pane">The <see cref="GraphPane" /> for which the label is to be
|
|
/// formatted</param>
|
|
/// <param name="axis">The <see cref="Scale" /> of interest.</param>
|
|
/// <param name="val">The value to be formatted</param>
|
|
/// <param name="index">The zero-based index of the label to be formatted</param>
|
|
/// <returns>
|
|
/// A string value representing the label, or null if the ZedGraph should go ahead
|
|
/// and generate the label according to the current settings</returns>
|
|
/// <seealso cref="ScaleFormatEvent" />
|
|
public delegate string ScaleFormatHandler( GraphPane pane, Axis axis, double val, int index );
|
|
|
|
/// <summary>
|
|
/// Subscribe to this event to handle custom formatting of the scale labels.
|
|
/// </summary>
|
|
public event ScaleFormatHandler ScaleFormatEvent;
|
|
|
|
// Revision: JCarpenter 10/06
|
|
/// <summary>
|
|
/// Allow customization of title based on user preferences.
|
|
/// </summary>
|
|
/// <param name="axis">The <see cref="Axis" /> of interest.</param>
|
|
/// <returns>
|
|
/// A string value representing the label, or null if the ZedGraph should go ahead
|
|
/// and generate the label according to the current settings. To make the title
|
|
/// blank, return "".</returns>
|
|
/// <seealso cref="ScaleFormatEvent" />
|
|
public delegate string ScaleTitleEventHandler( Axis axis );
|
|
|
|
//Revision: JCarpenter 10/06
|
|
/// <summary>
|
|
/// Allow customization of the title when the scale is very large
|
|
/// Subscribe to this event to handle custom formatting of the scale axis label.
|
|
/// </summary>
|
|
public event ScaleTitleEventHandler ScaleTitleEvent;
|
|
|
|
#endregion
|
|
|
|
#region Defaults
|
|
|
|
/// <summary>
|
|
/// A simple struct that defines the
|
|
/// default property values for the <see cref="Axis"/> class.
|
|
/// </summary>
|
|
public struct Default
|
|
{
|
|
/// <summary>
|
|
/// The default size for the gap between multiple axes
|
|
/// (<see cref="Axis.AxisGap"/> property). Units are in points (1/72 inch).
|
|
/// </summary>
|
|
public static float AxisGap = 5;
|
|
|
|
/// <summary>
|
|
/// The default setting for the gap between the scale labels and the axis title.
|
|
/// </summary>
|
|
public static float TitleGap = 0.0f;
|
|
|
|
/// <summary>
|
|
/// The default font family for the <see cref="Axis"/> <see cref="Title" /> text
|
|
/// font specification <see cref="FontSpec"/>
|
|
/// (<see cref="FontSpec.Family"/> property).
|
|
/// </summary>
|
|
public static string TitleFontFamily = "Arial";
|
|
/// <summary>
|
|
/// The default font size for the <see cref="Axis"/> <see cref="Title" /> text
|
|
/// font specification <see cref="FontSpec"/>
|
|
/// (<see cref="FontSpec.Size"/> property). Units are
|
|
/// in points (1/72 inch).
|
|
/// </summary>
|
|
public static float TitleFontSize = 14;
|
|
/// <summary>
|
|
/// The default font color for the <see cref="Axis"/> <see cref="Title" /> text
|
|
/// font specification <see cref="FontSpec"/>
|
|
/// (<see cref="FontSpec.FontColor"/> property).
|
|
/// </summary>
|
|
public static Color TitleFontColor = Color.Black;
|
|
/// <summary>
|
|
/// The default font bold mode for the <see cref="Axis"/> <see cref="Title" /> text
|
|
/// font specification <see cref="FontSpec"/>
|
|
/// (<see cref="FontSpec.IsBold"/> property). true
|
|
/// for a bold typeface, false otherwise.
|
|
/// </summary>
|
|
public static bool TitleFontBold = true;
|
|
/// <summary>
|
|
/// The default font italic mode for the <see cref="Axis"/> <see cref="Title" /> text
|
|
/// font specification <see cref="FontSpec"/>
|
|
/// (<see cref="FontSpec.IsItalic"/> property). true
|
|
/// for an italic typeface, false otherwise.
|
|
/// </summary>
|
|
public static bool TitleFontItalic = false;
|
|
/// <summary>
|
|
/// The default font underline mode for the <see cref="Axis"/> <see cref="Title" /> text
|
|
/// font specification <see cref="FontSpec"/>
|
|
/// (<see cref="FontSpec.IsUnderline"/> property). true
|
|
/// for an underlined typeface, false otherwise.
|
|
/// </summary>
|
|
public static bool TitleFontUnderline = false;
|
|
/// <summary>
|
|
/// The default color for filling in the <see cref="Title" /> text background
|
|
/// (see <see cref="ZedGraph.Fill.Color"/> property).
|
|
/// </summary>
|
|
public static Color TitleFillColor = Color.White;
|
|
/// <summary>
|
|
/// The default custom brush for filling in the <see cref="Title" /> text background
|
|
/// (see <see cref="ZedGraph.Fill.Brush"/> property).
|
|
/// </summary>
|
|
public static Brush TitleFillBrush = null;
|
|
/// <summary>
|
|
/// The default fill mode for filling in the <see cref="Title" /> text background
|
|
/// (see <see cref="ZedGraph.Fill.Type"/> property).
|
|
/// </summary>
|
|
public static FillType TitleFillType = FillType.None;
|
|
|
|
/// <summary>
|
|
/// The default color for the <see cref="Axis"/> itself
|
|
/// (<see cref="Axis.Color"/> property). This color only affects the
|
|
/// the axis border.
|
|
/// </summary>
|
|
public static Color BorderColor = Color.Black;
|
|
/// <summary>
|
|
/// The default value for <see cref="Axis.IsAxisSegmentVisible"/>, which determines
|
|
/// whether or not the scale segment itself is visible
|
|
/// </summary>
|
|
public static bool IsAxisSegmentVisible = true;
|
|
|
|
/// <summary>
|
|
/// The default setting for the <see cref="Axis"/> scale axis type
|
|
/// (<see cref="Axis.Type"/> property). This value is set as per
|
|
/// the <see cref="AxisType"/> enumeration
|
|
/// </summary>
|
|
public static AxisType Type = AxisType.Linear;
|
|
|
|
/// <summary>
|
|
/// The default color for the axis segment.
|
|
/// </summary>
|
|
public static Color Color = Color.Black;
|
|
|
|
/// <summary>
|
|
/// The default setting for the axis space allocation. This term, expressed in
|
|
/// points (1/72 inch) and scaled according to <see cref="PaneBase.CalcScaleFactor"/> for the
|
|
/// <see cref="GraphPane"/>, determines the minimum amount of space an axis must
|
|
/// have between the <see cref="Chart.Rect"/> and the
|
|
/// <see cref="PaneBase.Rect"/>. This minimum space
|
|
/// applies whether <see cref="Axis.IsVisible"/> is true or false.
|
|
/// </summary>
|
|
public static float MinSpace = 0f;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Constructors
|
|
|
|
/// <summary>
|
|
/// Default constructor for <see cref="Axis"/> that sets all axis properties
|
|
/// to default values as defined in the <see cref="Default"/> class.
|
|
/// </summary>
|
|
public Axis()
|
|
{
|
|
_scale = new LinearScale( this );
|
|
|
|
_cross = 0.0;
|
|
|
|
_crossAuto = true;
|
|
|
|
_majorTic = new MajorTic();
|
|
_minorTic = new MinorTic();
|
|
|
|
_majorGrid = new MajorGrid();
|
|
_minorGrid = new MinorGrid();
|
|
|
|
_axisGap = Default.AxisGap;
|
|
|
|
_minSpace = Default.MinSpace;
|
|
_isVisible = true;
|
|
|
|
_isAxisSegmentVisible = Default.IsAxisSegmentVisible;
|
|
|
|
_title = new AxisLabel( "", Default.TitleFontFamily, Default.TitleFontSize,
|
|
Default.TitleFontColor, Default.TitleFontBold,
|
|
Default.TitleFontUnderline, Default.TitleFontItalic );
|
|
_title.FontSpec.Fill = new Fill( Default.TitleFillColor, Default.TitleFillBrush,
|
|
Default.TitleFillType );
|
|
|
|
_title.FontSpec.Border.IsVisible = false;
|
|
|
|
|
|
_color = Default.Color;
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructor for <see cref="Axis"/> that sets all axis properties
|
|
/// to default values as defined in the <see cref="Default"/> class,
|
|
/// except for the <see cref="Title"/>.
|
|
/// </summary>
|
|
/// <param name="title">A string containing the axis title</param>
|
|
public Axis( string title )
|
|
: this()
|
|
{
|
|
_title._text = title;
|
|
}
|
|
|
|
/// <summary>
|
|
/// The Copy Constructor.
|
|
/// </summary>
|
|
/// <param name="rhs">The Axis object from which to copy</param>
|
|
public Axis( Axis rhs )
|
|
{
|
|
_scale = rhs._scale.Clone( this );
|
|
|
|
_cross = rhs._cross;
|
|
|
|
_crossAuto = rhs._crossAuto;
|
|
|
|
_majorTic = rhs.MajorTic.Clone();
|
|
_minorTic = rhs.MinorTic.Clone();
|
|
|
|
_majorGrid = rhs._majorGrid.Clone();
|
|
_minorGrid = rhs._minorGrid.Clone();
|
|
|
|
_isVisible = rhs.IsVisible;
|
|
|
|
_isAxisSegmentVisible = rhs._isAxisSegmentVisible;
|
|
|
|
_title = (AxisLabel) rhs.Title.Clone();
|
|
|
|
_axisGap = rhs._axisGap;
|
|
|
|
_minSpace = rhs.MinSpace;
|
|
|
|
_color = rhs.Color;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
|
|
/// calling the typed version of Clone.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Note that this method must be called with an explicit cast to ICloneable, and
|
|
/// that it is inherently virtual. For example:
|
|
/// <code>
|
|
/// ParentClass foo = new ChildClass();
|
|
/// ChildClass bar = (ChildClass) ((ICloneable)foo).Clone();
|
|
/// </code>
|
|
/// Assume that ChildClass is inherited from ParentClass. Even though foo is declared with
|
|
/// ParentClass, it is actually an instance of ChildClass. Calling the ICloneable implementation
|
|
/// of Clone() on foo actually calls ChildClass.Clone() as if it were a virtual function.
|
|
/// </remarks>
|
|
/// <returns>A deep copy of this object</returns>
|
|
object ICloneable.Clone()
|
|
{
|
|
throw new NotImplementedException( "Can't clone an abstract base type -- child types must implement ICloneable" );
|
|
//return new PaneBase( this );
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Serialization
|
|
|
|
/// <summary>
|
|
/// Current schema value that defines the version of the serialized file
|
|
/// </summary>
|
|
public const int schema = 10;
|
|
|
|
/// <summary>
|
|
/// Constructor for deserializing objects
|
|
/// </summary>
|
|
/// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
|
|
/// </param>
|
|
/// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
|
|
/// </param>
|
|
protected Axis( SerializationInfo info, StreamingContext context )
|
|
{
|
|
// The schema value is just a file version parameter. You can use it to make future versions
|
|
// backwards compatible as new member variables are added to classes
|
|
int sch = info.GetInt32( "schema" );
|
|
|
|
_cross = info.GetDouble( "cross" );
|
|
_crossAuto = info.GetBoolean( "crossAuto" );
|
|
|
|
_majorTic = (MajorTic)info.GetValue( "MajorTic", typeof( MajorTic ) );
|
|
_minorTic = (MinorTic)info.GetValue( "MinorTic", typeof( MinorTic ) );
|
|
_majorGrid = (MajorGrid)info.GetValue( "majorGrid", typeof( MajorGrid ) );
|
|
_minorGrid = (MinorGrid)info.GetValue( "minorGrid", typeof( MinorGrid ) );
|
|
|
|
_isVisible = info.GetBoolean( "isVisible" );
|
|
|
|
_title = (AxisLabel) info.GetValue( "title", typeof( AxisLabel ) );
|
|
|
|
_minSpace = info.GetSingle( "minSpace" );
|
|
|
|
_color = (Color)info.GetValue( "color", typeof( Color ) );
|
|
|
|
_isAxisSegmentVisible = info.GetBoolean( "isAxisSegmentVisible" );
|
|
|
|
|
|
_axisGap = info.GetSingle( "axisGap" );
|
|
|
|
_scale = (Scale)info.GetValue( "scale", typeof( Scale ) );
|
|
_scale._ownerAxis = this;
|
|
|
|
}
|
|
/// <summary>
|
|
/// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
|
|
/// </summary>
|
|
/// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
|
|
/// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
|
|
[SecurityPermissionAttribute( SecurityAction.Demand, SerializationFormatter = true )]
|
|
public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
|
|
{
|
|
info.AddValue( "schema", schema );
|
|
|
|
info.AddValue( "cross", _cross );
|
|
info.AddValue( "crossAuto", _crossAuto );
|
|
|
|
info.AddValue( "MajorTic", MajorTic );
|
|
info.AddValue( "MinorTic", MinorTic );
|
|
info.AddValue( "majorGrid", _majorGrid );
|
|
info.AddValue( "minorGrid", _minorGrid );
|
|
|
|
info.AddValue( "isVisible", _isVisible );
|
|
|
|
info.AddValue( "title", _title );
|
|
|
|
info.AddValue( "minSpace", _minSpace );
|
|
|
|
info.AddValue( "color", _color );
|
|
|
|
info.AddValue( "isAxisSegmentVisible", _isAxisSegmentVisible );
|
|
|
|
info.AddValue( "axisGap", _axisGap );
|
|
|
|
info.AddValue( "scale", _scale );
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Scale Properties
|
|
|
|
/// <summary>
|
|
/// Gets the <see cref="Scale" /> instance associated with this <see cref="Axis" />.
|
|
/// </summary>
|
|
public Scale Scale
|
|
{
|
|
get { return _scale; }
|
|
}
|
|
/// <summary>
|
|
/// Gets or sets the scale value at which this axis should cross the "other" axis.
|
|
/// </summary>
|
|
/// <remarks>This property allows the axis to be shifted away from its default location.
|
|
/// For example, for a graph with an X range from -100 to +100, the Y Axis can be located
|
|
/// at the X=0 value rather than the left edge of the ChartRect. This value can be set
|
|
/// automatically based on the state of <see cref="CrossAuto"/>. If
|
|
/// this value is set manually, then <see cref="CrossAuto"/> will
|
|
/// also be set to false. The "other" axis is the axis the handles the second dimension
|
|
/// for the graph. For the XAxis, the "other" axis is the YAxis. For the YAxis or
|
|
/// Y2Axis, the "other" axis is the XAxis.
|
|
/// </remarks>
|
|
/// <value> The value is defined in user scale units </value>
|
|
/// <seealso cref="ZedGraph.Scale.Min"/>
|
|
/// <seealso cref="ZedGraph.Scale.Max"/>
|
|
/// <seealso cref="ZedGraph.Scale.MajorStep"/>
|
|
/// <seealso cref="CrossAuto"/>
|
|
public double Cross
|
|
{
|
|
get { return _cross; }
|
|
set { _cross = value; _crossAuto = false; }
|
|
}
|
|
/// <summary>
|
|
/// Gets or sets a value that determines whether or not the <see cref="Cross"/> value
|
|
/// is set automatically.
|
|
/// </summary>
|
|
/// <value>Set to true to have ZedGraph put the axis in the default location, or false
|
|
/// to specify the axis location manually with a <see cref="Cross"/> value.</value>
|
|
/// <seealso cref="ZedGraph.Scale.Min"/>
|
|
/// <seealso cref="ZedGraph.Scale.Max"/>
|
|
/// <seealso cref="ZedGraph.Scale.MajorStep"/>
|
|
/// <seealso cref="Cross"/>
|
|
public bool CrossAuto
|
|
{
|
|
get { return _crossAuto; }
|
|
set { _crossAuto = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the minimum axis space allocation.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This term, expressed in
|
|
/// points (1/72 inch) and scaled according to <see cref="PaneBase.CalcScaleFactor"/>
|
|
/// for the <see cref="GraphPane"/>, determines the minimum amount of space
|
|
/// an axis must have between the <see cref="Chart.Rect">Chart.Rect</see> and the
|
|
/// <see cref="PaneBase.Rect">GraphPane.Rect</see>. This minimum space
|
|
/// applies whether <see cref="IsVisible"/> is true or false.
|
|
/// </remarks>
|
|
public float MinSpace
|
|
{
|
|
get { return _minSpace; }
|
|
set { _minSpace = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Tic Properties
|
|
|
|
/// <summary>
|
|
/// The color to use for drawing this <see cref="Axis"/>.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This affects only the axis segment (see <see cref="IsAxisSegmentVisible" />),
|
|
/// since the <see cref="Title"/>,
|
|
/// <see cref="Scale"/>, <see cref="MajorTic" />, <see cref="MinorTic" />,
|
|
/// <see cref="MajorGrid" />, and <see cref="MinorGrid" />
|
|
/// all have their own color specification.
|
|
/// </remarks>
|
|
/// <value> The color is defined using the
|
|
/// <see cref="System.Drawing.Color"/> class</value>
|
|
/// <seealso cref="Default.Color"/>.
|
|
/// <seealso cref="IsVisible"/>
|
|
public Color Color
|
|
{
|
|
get { return _color; }
|
|
set { _color = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a reference to the <see cref="ZedGraph.MajorTic" /> class instance
|
|
/// for this <see cref="Axis" />. This class stores all the major tic settings.
|
|
/// </summary>
|
|
public MajorTic MajorTic
|
|
{
|
|
get { return _majorTic; }
|
|
}
|
|
/// <summary>
|
|
/// Gets a reference to the <see cref="ZedGraph.MinorTic" /> class instance
|
|
/// for this <see cref="Axis" />. This class stores all the minor tic settings.
|
|
/// </summary>
|
|
public MinorTic MinorTic
|
|
{
|
|
get { return _minorTic; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Grid Properties
|
|
|
|
/// <summary>
|
|
/// Gets a reference to the <see cref="MajorGrid" /> class that contains the properties
|
|
/// of the major grid.
|
|
/// </summary>
|
|
public MajorGrid MajorGrid
|
|
{
|
|
get { return _majorGrid; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a reference to the <see cref="MinorGrid" /> class that contains the properties
|
|
/// of the minor grid.
|
|
/// </summary>
|
|
public MinorGrid MinorGrid
|
|
{
|
|
get { return _minorGrid; }
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
#region Type Properties
|
|
|
|
/// <summary>
|
|
/// This property determines whether or not the <see cref="Axis"/> is shown.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Note that even if
|
|
/// the axis is not visible, it can still be actively used to draw curves on a
|
|
/// graph, it will just be invisible to the user
|
|
/// </remarks>
|
|
/// <value>true to show the axis, false to disable all drawing of this axis</value>
|
|
/// <seealso cref="ZedGraph.Scale.IsVisible"/>.
|
|
/// <seealso cref="XAxis.Default.IsVisible"/>.
|
|
/// <seealso cref="YAxis.Default.IsVisible"/>.
|
|
/// <seealso cref="Y2Axis.Default.IsVisible"/>.
|
|
public bool IsVisible
|
|
{
|
|
get { return _isVisible; }
|
|
set { _isVisible = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets a property that determines whether or not the axis segment (the line that
|
|
/// represents the axis itself) is drawn.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Under normal circumstances, this value won't affect the appearance of the display because
|
|
/// the Axis segment is overlain by the Axis border (see <see cref="Chart.Border"/>).
|
|
/// However, when the border is not visible, or when <see cref="Axis.CrossAuto"/> is set to
|
|
/// false, this value will make a difference.
|
|
/// </remarks>
|
|
public bool IsAxisSegmentVisible
|
|
{
|
|
get { return _isAxisSegmentVisible; }
|
|
set { _isAxisSegmentVisible = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the <see cref="AxisType"/> for this <see cref="Axis"/>.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The type can be either <see cref="AxisType.Linear"/>,
|
|
/// <see cref="AxisType.Log"/>, <see cref="AxisType.Date"/>,
|
|
/// or <see cref="AxisType.Text"/>.
|
|
/// </remarks>
|
|
/// <seealso cref="ZedGraph.Scale.IsLog"/>
|
|
/// <seealso cref="ZedGraph.Scale.IsText"/>
|
|
/// <seealso cref="ZedGraph.Scale.IsOrdinal"/>
|
|
/// <seealso cref="ZedGraph.Scale.IsDate"/>
|
|
/// <seealso cref="ZedGraph.Scale.IsReverse"/>
|
|
public AxisType Type
|
|
{
|
|
get { return _scale.Type; }
|
|
set { _scale = Scale.MakeNewScale( _scale, value ); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Label Properties
|
|
|
|
/// <summary>
|
|
/// Gets or sets the <see cref="Label" /> class that contains the title of this
|
|
/// <see cref="Axis"/>.
|
|
/// </summary>
|
|
/// <remarks>The title normally shows the basis and dimensions of
|
|
/// the scale range, such as "Time (Years)". The title is only shown if the
|
|
/// <see cref="Label.IsVisible"/> property is set to true. If the Title text is empty,
|
|
/// then no title is shown, and no space is "reserved" for the title on the graph.
|
|
/// </remarks>
|
|
/// <value>the title is a string value</value>
|
|
/// <seealso cref="AxisLabel.IsOmitMag"/>
|
|
public AxisLabel Title
|
|
{
|
|
get { return _title; }
|
|
set { _title = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The size of the gap between multiple axes (see <see cref="GraphPane.YAxisList" /> and
|
|
/// <see cref="GraphPane.Y2AxisList" />).
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This size will be scaled
|
|
/// according to the <see cref="PaneBase.CalcScaleFactor"/> for the
|
|
/// <see cref="GraphPane"/>
|
|
/// </remarks>
|
|
/// <value>The axis gap is measured in points (1/72 inch)</value>
|
|
/// <seealso cref="Default.AxisGap"/>.
|
|
public float AxisGap
|
|
{
|
|
get { return _axisGap; }
|
|
set { _axisGap = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Rendering Methods
|
|
|
|
/// <summary>
|
|
/// Restore the scale ranging to automatic mode, and recalculate the
|
|
/// <see cref="Axis"/> scale ranges
|
|
/// </summary>
|
|
/// <param name="pane">
|
|
/// A reference to the <see cref="GraphPane"/> object that is the parent or
|
|
/// owner of this object.
|
|
/// </param>
|
|
/// <param name="g">
|
|
/// A graphic device object to be drawn into. This is normally e.Graphics from the
|
|
/// PaintEventArgs argument to the Paint() method.
|
|
/// </param>
|
|
/// <seealso cref="ZedGraph.Scale.MinAuto"/>
|
|
/// <seealso cref="ZedGraph.Scale.MaxAuto"/>
|
|
/// <seealso cref="ZedGraph.Scale.MajorStepAuto"/>
|
|
/// <seealso cref="ZedGraph.Scale.MagAuto"/>
|
|
/// <seealso cref="ZedGraph.Scale.FormatAuto"/>
|
|
public void ResetAutoScale( GraphPane pane, Graphics g )
|
|
{
|
|
_scale._minAuto = true;
|
|
_scale._maxAuto = true;
|
|
_scale._majorStepAuto = true;
|
|
_scale._minorStepAuto = true;
|
|
_crossAuto = true;
|
|
_scale._magAuto = true;
|
|
//this.numDecAuto = true;
|
|
_scale._formatAuto = true;
|
|
pane.AxisChange( g );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Do all rendering associated with this <see cref="Axis"/> to the specified
|
|
/// <see cref="Graphics"/> device.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This method is normally only
|
|
/// called by the Draw method of the parent <see cref="GraphPane"/> object.
|
|
/// </remarks>
|
|
/// <param name="g">
|
|
/// A graphic device object to be drawn into. This is normally e.Graphics from the
|
|
/// PaintEventArgs argument to the Paint() method.
|
|
/// </param>
|
|
/// <param name="pane">
|
|
/// A reference to the <see cref="GraphPane"/> object that is the parent or
|
|
/// owner of this object.
|
|
/// </param>
|
|
/// <param name="scaleFactor">
|
|
/// The scaling factor to be used for rendering objects. This is calculated and
|
|
/// passed down by the parent <see cref="GraphPane"/> object using the
|
|
/// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
|
|
/// font sizes, etc. according to the actual size of the graph.
|
|
/// </param>
|
|
/// <param name="shiftPos">
|
|
/// The number of pixels to shift to account for non-primary axis position (e.g.,
|
|
/// the second, third, fourth, etc. <see cref="YAxis" /> or <see cref="Y2Axis" />.
|
|
/// </param>
|
|
public void Draw( Graphics g, GraphPane pane, float scaleFactor, float shiftPos )
|
|
{
|
|
Matrix saveMatrix = g.Transform;
|
|
|
|
_scale.SetupScaleData( pane, this );
|
|
|
|
if ( _isVisible )
|
|
{
|
|
SetTransformMatrix( g, pane, scaleFactor );
|
|
|
|
shiftPos = CalcTotalShift( pane, scaleFactor, shiftPos );
|
|
|
|
_scale.Draw( g, pane, scaleFactor, shiftPos );
|
|
|
|
//DrawTitle( g, pane, scaleFactor );
|
|
|
|
g.Transform = saveMatrix;
|
|
}
|
|
}
|
|
|
|
internal void DrawGrid( Graphics g, GraphPane pane, float scaleFactor, float shiftPos )
|
|
{
|
|
if ( _isVisible )
|
|
{
|
|
Matrix saveMatrix = g.Transform;
|
|
SetTransformMatrix( g, pane, scaleFactor );
|
|
|
|
double baseVal = _scale.CalcBaseTic();
|
|
float topPix, rightPix;
|
|
_scale.GetTopRightPix( pane, out topPix, out rightPix );
|
|
|
|
shiftPos = CalcTotalShift( pane, scaleFactor, shiftPos );
|
|
|
|
_scale.DrawGrid( g, pane, baseVal, topPix, scaleFactor );
|
|
|
|
DrawMinorTics( g, pane, baseVal, shiftPos, scaleFactor, topPix );
|
|
|
|
g.Transform = saveMatrix;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// This method will set the <see cref="MinSpace"/> property for this <see cref="Axis"/>
|
|
/// using the currently required space multiplied by a fraction (<paramref>bufferFraction</paramref>).
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The currently required space is calculated using <see cref="CalcSpace"/>, and is
|
|
/// based on current data ranges, font sizes, etc. The "space" is actually the amount of space
|
|
/// required to fit the tic marks, scale labels, and axis title.
|
|
/// </remarks>
|
|
/// <param name="g">A graphic device object to be drawn into. This is normally e.Graphics from the
|
|
/// PaintEventArgs argument to the Paint() method.</param>
|
|
/// <param name="pane">A reference to the <see cref="GraphPane"/> object that is the parent or
|
|
/// owner of this object.</param>
|
|
/// <param name="bufferFraction">The amount of space to allocate for the axis, expressed
|
|
/// as a fraction of the currently required space. For example, a value of 1.2 would
|
|
/// allow for 20% extra above the currently required space.</param>
|
|
/// <param name="isGrowOnly">If true, then this method will only modify the <see cref="MinSpace"/>
|
|
/// property if the calculated result is more than the current value.</param>
|
|
public void SetMinSpaceBuffer( Graphics g, GraphPane pane, float bufferFraction,
|
|
bool isGrowOnly )
|
|
{
|
|
// save the original value of minSpace
|
|
float oldSpace = this.MinSpace;
|
|
// set minspace to zero, since we don't want it to affect the CalcSpace() result
|
|
this.MinSpace = 0;
|
|
// Calculate the space required for the current graph assuming scalefactor = 1.0
|
|
// and apply the bufferFraction
|
|
float fixedSpace;
|
|
float space = this.CalcSpace( g, pane, 1.0F, out fixedSpace ) * bufferFraction;
|
|
// isGrowOnly indicates the minSpace can grow but not shrink
|
|
if ( isGrowOnly )
|
|
space = Math.Max( oldSpace, space );
|
|
// Set the minSpace
|
|
this.MinSpace = space;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Setup the Transform Matrix to handle drawing of this <see cref="Axis"/>
|
|
/// </summary>
|
|
/// <param name="g">
|
|
/// A graphic device object to be drawn into. This is normally e.Graphics from the
|
|
/// PaintEventArgs argument to the Paint() method.
|
|
/// </param>
|
|
/// <param name="pane">
|
|
/// A reference to the <see cref="GraphPane"/> object that is the parent or
|
|
/// owner of this object.
|
|
/// </param>
|
|
/// <param name="scaleFactor">
|
|
/// The scaling factor to be used for rendering objects. This is calculated and
|
|
/// passed down by the parent <see cref="GraphPane"/> object using the
|
|
/// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
|
|
/// font sizes, etc. according to the actual size of the graph.
|
|
/// </param>
|
|
abstract public void SetTransformMatrix( Graphics g, GraphPane pane, float scaleFactor );
|
|
|
|
|
|
/// <summary>
|
|
/// Calculate the "shift" size, in pixels, in order to shift the axis from its default
|
|
/// location to the value specified by <see cref="Cross"/>.
|
|
/// </summary>
|
|
/// <param name="pane">
|
|
/// A reference to the <see cref="GraphPane"/> object that is the parent or
|
|
/// owner of this object.
|
|
/// </param>
|
|
/// <returns>The shift amount measured in pixels</returns>
|
|
abstract internal float CalcCrossShift( GraphPane pane );
|
|
|
|
/// <summary>
|
|
/// Gets the "Cross" axis that corresponds to this axis.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The cross axis is the axis which determines the of this Axis when the
|
|
/// <see cref="Axis.Cross" >Axis.Cross</see> property is used. The
|
|
/// cross axis for any <see cref="XAxis" /> or <see cref="X2Axis" />
|
|
/// is always the primary <see cref="YAxis" />, and
|
|
/// the cross axis for any <see cref="YAxis" /> or <see cref="Y2Axis" /> is
|
|
/// always the primary <see cref="XAxis" />.
|
|
/// </remarks>
|
|
/// <param name="pane">
|
|
/// A reference to the <see cref="GraphPane"/> object that is the parent or
|
|
/// owner of this object.
|
|
/// </param>
|
|
abstract public Axis GetCrossAxis( GraphPane pane );
|
|
|
|
// abstract internal float GetMinPix( GraphPane pane );
|
|
|
|
//abstract internal float CalcCrossFraction( GraphPane pane );
|
|
|
|
/// <summary>
|
|
/// Returns the linearized actual cross position for this axis, reflecting the settings of
|
|
/// <see cref="Cross" />, <see cref="CrossAuto" />, and <see cref="ZedGraph.Scale.IsReverse" />.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// If the value of <see cref="Cross" /> lies outside the axis range, it is
|
|
/// limited to the axis range.
|
|
/// </remarks>
|
|
internal double EffectiveCrossValue( GraphPane pane )
|
|
{
|
|
Axis crossAxis = GetCrossAxis( pane );
|
|
|
|
// Use Linearize here instead of _minLinTemp because this method is called
|
|
// as part of CalcRect() before scale is fully setup
|
|
double min = crossAxis._scale.Linearize( _scale._min );
|
|
double max = crossAxis._scale.Linearize( _scale._max );
|
|
|
|
if ( _crossAuto )
|
|
{
|
|
if ( crossAxis._scale.IsReverse == ( this is Y2Axis || this is X2Axis ) )
|
|
return max;
|
|
else
|
|
return min;
|
|
}
|
|
else if ( _cross < min )
|
|
return min;
|
|
else if ( _cross > max )
|
|
return max;
|
|
else
|
|
return _scale.Linearize( _cross );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if the axis is shifted at all due to the setting of
|
|
/// <see cref="Cross" />. This function will always return false if
|
|
/// <see cref="CrossAuto" /> is true.
|
|
/// </summary>
|
|
internal bool IsCrossShifted( GraphPane pane )
|
|
{
|
|
if ( _crossAuto )
|
|
return false;
|
|
else
|
|
{
|
|
Axis crossAxis = GetCrossAxis( pane );
|
|
if ( ( ( this is XAxis || this is YAxis ) && !crossAxis._scale.IsReverse ) ||
|
|
( ( this is X2Axis || this is Y2Axis ) && crossAxis._scale.IsReverse ) )
|
|
{
|
|
if ( _cross <= crossAxis._scale._min )
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
if ( _cross >= crossAxis._scale._max )
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculates the proportional fraction of the total cross axis width at which
|
|
/// this axis is located.
|
|
/// </summary>
|
|
/// <param name="pane"></param>
|
|
/// <returns></returns>
|
|
internal float CalcCrossFraction( GraphPane pane )
|
|
{
|
|
// if this axis is not shifted due to the Cross value
|
|
if ( !this.IsCrossShifted( pane ) )
|
|
{
|
|
// if it's the primary axis and the scale labels are on the inside, then we
|
|
// don't need to save any room for the axis labels (they will be inside the chart rect)
|
|
if ( IsPrimary( pane ) && _scale._isLabelsInside )
|
|
return 1.0f;
|
|
// otherwise, it's a secondary (outboard) axis and we always save room for the axis and labels.
|
|
else
|
|
return 0.0f;
|
|
}
|
|
|
|
double effCross = EffectiveCrossValue( pane );
|
|
Axis crossAxis = GetCrossAxis( pane );
|
|
|
|
// Use Linearize here instead of _minLinTemp because this method is called
|
|
// as part of CalcRect() before scale is fully setup
|
|
// double max = crossAxis._scale._maxLinTemp;
|
|
// double min = crossAxis._scale._minLinTemp;
|
|
double max = crossAxis._scale.Linearize( _scale._min );
|
|
double min = crossAxis._scale.Linearize( _scale._max );
|
|
float frac;
|
|
|
|
if ( ( ( this is XAxis || this is YAxis ) && _scale._isLabelsInside == crossAxis._scale.IsReverse ) ||
|
|
( ( this is X2Axis || this is Y2Axis ) && _scale._isLabelsInside != crossAxis._scale.IsReverse ) )
|
|
frac = (float)( ( effCross - min ) / ( max - min ) );
|
|
else
|
|
frac = (float)( ( max - effCross ) / ( max - min ) );
|
|
|
|
if ( frac < 0.0f )
|
|
frac = 0.0f;
|
|
if ( frac > 1.0f )
|
|
frac = 1.0f;
|
|
|
|
return frac;
|
|
}
|
|
|
|
private float CalcTotalShift( GraphPane pane, float scaleFactor, float shiftPos )
|
|
{
|
|
if ( !IsPrimary( pane ) )
|
|
{
|
|
// if ( CalcCrossFraction( pane ) != 0.0 )
|
|
if ( IsCrossShifted( pane ) )
|
|
{
|
|
shiftPos = 0;
|
|
}
|
|
else
|
|
{
|
|
// Scaled size (pixels) of a tic
|
|
float ticSize = _majorTic.ScaledTic( scaleFactor );
|
|
|
|
// if the scalelabels are on the inside, shift everything so the axis is drawn,
|
|
// for example, to the left side of the available space for a YAxis type
|
|
if ( _scale._isLabelsInside )
|
|
{
|
|
shiftPos += _tmpSpace;
|
|
|
|
// shift the axis to leave room for the outside tics
|
|
if ( _majorTic.IsOutside || _majorTic._isCrossOutside ||
|
|
_minorTic.IsOutside || _minorTic._isCrossOutside )
|
|
shiftPos -= ticSize;
|
|
}
|
|
else
|
|
{
|
|
// if it's not the primary axis, add a tic space for the spacing between axes
|
|
shiftPos += _axisGap * scaleFactor;
|
|
|
|
// if it has inside tics, leave another tic space
|
|
if ( _majorTic.IsInside || _majorTic._isCrossInside ||
|
|
_minorTic.IsInside || _minorTic._isCrossInside )
|
|
shiftPos += ticSize;
|
|
}
|
|
}
|
|
}
|
|
|
|
// shift is the position of the actual axis line itself
|
|
// everything else is based on that position.
|
|
float crossShift = CalcCrossShift( pane );
|
|
shiftPos += crossShift;
|
|
|
|
return shiftPos;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate the space required (pixels) for this <see cref="Axis"/> object.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This is the total space (vertical space for the X axis, horizontal space for
|
|
/// the Y axes) required to contain the axis. If <see cref="Cross" /> is zero, then
|
|
/// this space will be the space required between the <see cref="Chart.Rect" /> and
|
|
/// the <see cref="PaneBase.Rect" />. This method sets the internal values of
|
|
/// <see cref="_tmpSpace" /> for use by the <see cref="GraphPane.CalcChartRect(Graphics)" />
|
|
/// method.
|
|
/// </remarks>
|
|
/// <param name="g">
|
|
/// A graphic device object to be drawn into. This is normally e.Graphics from the
|
|
/// PaintEventArgs argument to the Paint() method.
|
|
/// </param>
|
|
/// <param name="pane">
|
|
/// A reference to the <see cref="GraphPane"/> object that is the parent or
|
|
/// owner of this object.
|
|
/// </param>
|
|
/// <param name="scaleFactor">
|
|
/// The scaling factor to be used for rendering objects. This is calculated and
|
|
/// passed down by the parent <see cref="GraphPane"/> object using the
|
|
/// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
|
|
/// font sizes, etc. according to the actual size of the graph.
|
|
/// </param>
|
|
/// <param name="fixedSpace">The amount of space (pixels) at the edge of the ChartRect
|
|
/// that is always required for this axis, even if the axis is shifted by the
|
|
/// <see cref="Cross" /> value.</param>
|
|
/// <returns>Returns the space, in pixels, required for this axis (between the
|
|
/// rect and ChartRect)</returns>
|
|
public float CalcSpace( Graphics g, GraphPane pane, float scaleFactor, out float fixedSpace )
|
|
{
|
|
//fixedSpace = 0;
|
|
|
|
//Typical character height for the scale font
|
|
float charHeight = _scale._fontSpec.GetHeight( scaleFactor );
|
|
// Scaled size (pixels) of a tic
|
|
float ticSize = _majorTic.ScaledTic( scaleFactor );
|
|
// Scaled size (pixels) of the axis gap
|
|
float axisGap = _axisGap * scaleFactor;
|
|
float scaledLabelGap = _scale._labelGap * charHeight;
|
|
float scaledTitleGap = _title.GetScaledGap( scaleFactor );
|
|
|
|
// The minimum amount of space to reserve for the NORMAL position of the axis. This would
|
|
// be the left side of the chart rect for the Y axis, the right side for the Y2 axis, etc.
|
|
// This amount of space is based on the need to reserve space for tics, etc., even if the
|
|
// Axis.Cross property causes the axis to be in a different location.
|
|
fixedSpace = 0;
|
|
|
|
// The actual space needed for this axis (ignoring the setting of Axis.Cross)
|
|
_tmpSpace = 0;
|
|
|
|
// Account for the Axis
|
|
if ( _isVisible )
|
|
{
|
|
bool hasTic = this.MajorTic.IsOutside || this.MajorTic._isCrossOutside ||
|
|
this.MinorTic.IsOutside || this.MinorTic._isCrossOutside;
|
|
|
|
// account for the tic space. Leave the tic space for any type of outside tic (Outside Tic Space)
|
|
if ( hasTic )
|
|
_tmpSpace += ticSize;
|
|
|
|
// if this is not the primary axis
|
|
if ( !IsPrimary( pane ) )
|
|
{
|
|
// always leave an extra tic space for the space between the multi-axes (Axis Gap)
|
|
_tmpSpace += axisGap;
|
|
|
|
// if it has inside tics, leave another tic space (Inside Tic Space)
|
|
if ( this.MajorTic._isInside || this.MajorTic._isCrossInside ||
|
|
this.MinorTic._isInside || this.MinorTic._isCrossInside )
|
|
_tmpSpace += ticSize;
|
|
}
|
|
|
|
// tic takes up 1x tic
|
|
// space between tic and scale label is 0.5 tic
|
|
// scale label is GetScaleMaxSpace()
|
|
// space between scale label and axis label is 0.5 tic
|
|
|
|
// account for the tic labels + 'LabelGap' tic gap between the tic and the label
|
|
_tmpSpace += _scale.GetScaleMaxSpace( g, pane, scaleFactor, true ).Height +
|
|
scaledLabelGap;
|
|
|
|
string str = MakeTitle();
|
|
|
|
// Only add space for the title if there is one
|
|
// Axis Title gets actual height
|
|
if ( str.Length > 0 && _title._isVisible )
|
|
{
|
|
//tmpSpace += this.TitleFontSpec.BoundingBox( g, str, scaleFactor ).Height;
|
|
fixedSpace = this.Title.FontSpec.BoundingBox( g, str, scaleFactor ).Height +
|
|
scaledTitleGap;
|
|
_tmpSpace += fixedSpace;
|
|
|
|
fixedSpace += scaledTitleGap;
|
|
}
|
|
|
|
if ( hasTic )
|
|
fixedSpace += ticSize;
|
|
}
|
|
|
|
// for the Y axes, make sure that enough space is left to fit the first
|
|
// and last X axis scale label
|
|
if ( this.IsPrimary( pane ) && ( (
|
|
( this is YAxis && (
|
|
( !pane.XAxis._scale._isSkipFirstLabel && !pane.XAxis._scale._isReverse ) ||
|
|
( !pane.XAxis._scale._isSkipLastLabel && pane.XAxis._scale._isReverse ) ) ) ||
|
|
( this is Y2Axis && (
|
|
( !pane.XAxis._scale._isSkipFirstLabel && pane.XAxis._scale._isReverse ) ||
|
|
( !pane.XAxis._scale._isSkipLastLabel && !pane.XAxis._scale._isReverse ) ) ) ) &&
|
|
pane.XAxis.IsVisible && pane.XAxis._scale._isVisible ) )
|
|
{
|
|
// half the width of the widest item, plus a gap of 1/2 the charheight
|
|
float tmp = pane.XAxis._scale.GetScaleMaxSpace( g, pane, scaleFactor, true ).Width / 2.0F;
|
|
//+ charHeight / 2.0F;
|
|
//if ( tmp > tmpSpace )
|
|
// tmpSpace = tmp;
|
|
|
|
fixedSpace = Math.Max( tmp, fixedSpace );
|
|
}
|
|
|
|
// Verify that the minSpace property was satisfied
|
|
_tmpSpace = Math.Max( _tmpSpace, _minSpace * (float)scaleFactor );
|
|
|
|
fixedSpace = Math.Max( fixedSpace, _minSpace * (float)scaleFactor );
|
|
|
|
return _tmpSpace;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines if this <see cref="Axis" /> object is a "primary" one.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The primary axes are the <see cref="XAxis" /> (always), the first
|
|
/// <see cref="YAxis" /> in the <see cref="GraphPane.YAxisList" />
|
|
/// (<see cref="CurveItem.YAxisIndex" /> = 0), and the first
|
|
/// <see cref="Y2Axis" /> in the <see cref="GraphPane.Y2AxisList" />
|
|
/// (<see cref="CurveItem.YAxisIndex" /> = 0). Note that
|
|
/// <see cref="GraphPane.YAxis" /> and <see cref="GraphPane.Y2Axis" />
|
|
/// always reference the primary axes.
|
|
/// </remarks>
|
|
/// <param name="pane">
|
|
/// A reference to the <see cref="GraphPane"/> object that is the parent or
|
|
/// owner of this object.
|
|
/// </param>
|
|
/// <returns>true for a primary <see cref="Axis" /> (for the <see cref="XAxis" />,
|
|
/// this is always true), false otherwise</returns>
|
|
abstract internal bool IsPrimary( GraphPane pane );
|
|
|
|
internal void FixZeroLine( Graphics g, GraphPane pane, float scaleFactor,
|
|
float left, float right )
|
|
{
|
|
// restore the zero line if needed (since the fill tends to cover it up)
|
|
if ( _isVisible && _majorGrid._isZeroLine &&
|
|
_scale._min < 0.0 && _scale._max > 0.0 )
|
|
{
|
|
float zeroPix = _scale.Transform( 0.0 );
|
|
|
|
using ( Pen zeroPen = new Pen( _color,
|
|
pane.ScaledPenWidth( _majorGrid._penWidth, scaleFactor ) ) )
|
|
{
|
|
g.DrawLine( zeroPen, left, zeroPix, right, zeroPix );
|
|
//zeroPen.Dispose();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Draw the minor tic marks as required for this <see cref="Axis"/>.
|
|
/// </summary>
|
|
/// <param name="g">
|
|
/// A graphic device object to be drawn into. This is normally e.Graphics from the
|
|
/// PaintEventArgs argument to the Paint() method.
|
|
/// </param>
|
|
/// <param name="pane">
|
|
/// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
|
|
/// owner of this object.
|
|
/// </param>
|
|
/// <param name="baseVal">
|
|
/// The scale value for the first major tic position. This is the reference point
|
|
/// for all other tic marks.
|
|
/// </param>
|
|
/// <param name="shift">The number of pixels to shift this axis, based on the
|
|
/// value of <see cref="Cross"/>. A positive value is into the ChartRect relative to
|
|
/// the default axis position.</param>
|
|
/// <param name="scaleFactor">
|
|
/// The scaling factor to be used for rendering objects. This is calculated and
|
|
/// passed down by the parent <see cref="GraphPane"/> object using the
|
|
/// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
|
|
/// font sizes, etc. according to the actual size of the graph.
|
|
/// </param>
|
|
/// <param name="topPix">
|
|
/// The pixel location of the far side of the ChartRect from this axis.
|
|
/// This value is the ChartRect.Height for the XAxis, or the ChartRect.Width
|
|
/// for the YAxis and Y2Axis.
|
|
/// </param>
|
|
public void DrawMinorTics( Graphics g, GraphPane pane, double baseVal, float shift,
|
|
float scaleFactor, float topPix )
|
|
{
|
|
if ( ( this.MinorTic.IsOutside || this.MinorTic.IsOpposite || this.MinorTic.IsInside ||
|
|
this.MinorTic._isCrossOutside || this.MinorTic._isCrossInside || _minorGrid._isVisible )
|
|
&& _isVisible )
|
|
{
|
|
double tMajor = _scale._majorStep * _scale.MajorUnitMultiplier,
|
|
tMinor = _scale._minorStep * _scale.MinorUnitMultiplier;
|
|
|
|
if ( _scale.IsLog || tMinor < tMajor )
|
|
{
|
|
float minorScaledTic = this.MinorTic.ScaledTic( scaleFactor );
|
|
|
|
// Minor tics start at the minimum value and step all the way thru
|
|
// the full scale. This means that if the minor step size is not
|
|
// an even division of the major step size, the minor tics won't
|
|
// line up with all of the scale labels and major tics.
|
|
double first = _scale._minLinTemp,
|
|
last = _scale._maxLinTemp;
|
|
|
|
double dVal = first;
|
|
float pixVal;
|
|
|
|
int iTic = _scale.CalcMinorStart( baseVal );
|
|
int MajorTic = 0;
|
|
double majorVal = _scale.CalcMajorTicValue( baseVal, MajorTic );
|
|
|
|
using ( Pen pen = new Pen( _minorTic._color,
|
|
pane.ScaledPenWidth( MinorTic._penWidth, scaleFactor ) ) )
|
|
using ( Pen minorGridPen = _minorGrid.GetPen( pane, scaleFactor ) )
|
|
{
|
|
|
|
// Draw the minor tic marks
|
|
while ( dVal < last && iTic < 5000 )
|
|
{
|
|
// Calculate the scale value for the current tic
|
|
dVal = _scale.CalcMinorTicValue( baseVal, iTic );
|
|
// Maintain a value for the current major tic
|
|
if ( dVal > majorVal )
|
|
majorVal = _scale.CalcMajorTicValue( baseVal, ++MajorTic );
|
|
|
|
// Make sure that the current value does not match up with a major tic
|
|
if ( ( ( Math.Abs( dVal ) < 1e-20 && Math.Abs( dVal - majorVal ) > 1e-20 ) ||
|
|
( Math.Abs( dVal ) > 1e-20 && Math.Abs( ( dVal - majorVal ) / dVal ) > 1e-10 ) ) &&
|
|
( dVal >= first && dVal <= last ) )
|
|
{
|
|
pixVal = _scale.LocalTransform( dVal );
|
|
|
|
_minorGrid.Draw( g, minorGridPen, pixVal, topPix );
|
|
|
|
_minorTic.Draw( g, pane, pen, pixVal, topPix, shift, minorScaledTic );
|
|
}
|
|
|
|
iTic++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Draw the title for this <see cref="Axis"/>.
|
|
/// </summary>
|
|
/// <remarks>On entry, it is assumed that the
|
|
/// graphics transform has been configured so that the origin is at the left side
|
|
/// of this axis, and the axis is aligned along the X coordinate direction.
|
|
/// </remarks>
|
|
/// <param name="g">
|
|
/// A graphic device object to be drawn into. This is normally e.Graphics from the
|
|
/// PaintEventArgs argument to the Paint() method.
|
|
/// </param>
|
|
/// <param name="pane">
|
|
/// A reference to the <see cref="GraphPane"/> object that is the parent or
|
|
/// owner of this object.
|
|
/// </param>
|
|
/// <param name="shiftPos">The number of pixels to shift this axis, based on the
|
|
/// value of <see cref="Cross"/>. A positive value is into the ChartRect relative to
|
|
/// the default axis position.</param>
|
|
/// <param name="scaleFactor">
|
|
/// The scaling factor to be used for rendering objects. This is calculated and
|
|
/// passed down by the parent <see cref="GraphPane"/> object using the
|
|
/// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
|
|
/// font sizes, etc. according to the actual size of the graph.
|
|
/// </param>
|
|
public void DrawTitle( Graphics g, GraphPane pane, float shiftPos, float scaleFactor )
|
|
{
|
|
string str = MakeTitle();
|
|
|
|
// If the Axis is visible, draw the title
|
|
if ( _isVisible && _title._isVisible && str.Length > 0 )
|
|
{
|
|
bool hasTic = ( _scale._isLabelsInside ?
|
|
( this.MajorTic.IsInside || this.MajorTic._isCrossInside ||
|
|
this.MinorTic.IsInside || this.MinorTic._isCrossInside ) :
|
|
( this.MajorTic.IsOutside || this.MajorTic._isCrossOutside || this.MinorTic.IsOutside || this.MinorTic._isCrossOutside ) );
|
|
|
|
// Calculate the title position in screen coordinates
|
|
float x = ( _scale._maxPix - _scale._minPix ) / 2;
|
|
|
|
float scaledTic = MajorTic.ScaledTic( scaleFactor );
|
|
float scaledLabelGap = _scale._fontSpec.GetHeight( scaleFactor ) * _scale._labelGap;
|
|
float scaledTitleGap = _title.GetScaledGap( scaleFactor );
|
|
|
|
// The space for the scale labels is only reserved if the axis is not shifted due to the
|
|
// cross value. Note that this could be a problem if the axis is only shifted slightly,
|
|
// since the scale value labels may overlap the axis title. However, it's not possible to
|
|
// calculate that actual shift amount at this point, because the ChartRect rect has not yet been
|
|
// calculated, and the cross value is determined using a transform of scale values (which
|
|
// rely on ChartRect).
|
|
|
|
float gap = scaledTic * ( hasTic ? 1.0f : 0.0f ) +
|
|
this.Title.FontSpec.BoundingBox( g, str, scaleFactor ).Height / 2.0F;
|
|
float y = ( _scale._isVisible ? _scale.GetScaleMaxSpace( g, pane, scaleFactor, true ).Height
|
|
+ scaledLabelGap : 0 );
|
|
|
|
if ( _scale._isLabelsInside )
|
|
y = shiftPos - y - gap;
|
|
else
|
|
y = shiftPos + y + gap;
|
|
|
|
if ( !_crossAuto && !_title._isTitleAtCross )
|
|
y = Math.Max( y, gap );
|
|
|
|
AlignV alignV = AlignV.Center;
|
|
|
|
// Add in the TitleGap space
|
|
y += scaledTitleGap;
|
|
|
|
// Draw the title
|
|
this.Title.FontSpec.Draw( g, pane, str, x, y,
|
|
AlignH.Center, alignV, scaleFactor );
|
|
}
|
|
}
|
|
|
|
private string MakeTitle()
|
|
{
|
|
// Revision: JCarpenter 10/06
|
|
// Allow customization of the modified title when the scale is very large
|
|
// The event handler can edit the full label. If the handler returns
|
|
// null, then the title will be the default.
|
|
if ( ScaleTitleEvent != null )
|
|
{
|
|
string label = ScaleTitleEvent( this );
|
|
if ( label != null )
|
|
return label;
|
|
}
|
|
|
|
// If the Mag is non-zero and IsOmitMag == false, and IsLog == false,
|
|
// then add the mag indicator to the title.
|
|
if ( _scale._mag != 0 && !_title._isOmitMag && !_scale.IsLog )
|
|
return _title._text + String.Format( " (10^{0})", _scale._mag );
|
|
else
|
|
return _title._text;
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Make a value label for the axis at the specified ordinal position.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This method properly accounts for <see cref="ZedGraph.Scale.IsLog"/>,
|
|
/// <see cref="ZedGraph.Scale.IsText"/>,
|
|
/// and other axis format settings. It also implements the ScaleFormatEvent such that
|
|
/// custom labels can be created.
|
|
/// </remarks>
|
|
/// <param name="pane">
|
|
/// A reference to the <see cref="GraphPane"/> object that is the parent or
|
|
/// owner of this object.
|
|
/// </param>
|
|
/// <param name="index">
|
|
/// The zero-based, ordinal index of the label to be generated. For example, a value of 2 would
|
|
/// cause the third value label on the axis to be generated.
|
|
/// </param>
|
|
/// <param name="dVal">
|
|
/// The numeric value associated with the label. This value is ignored for log
|
|
/// (<see cref="ZedGraph.Scale.IsLog"/>)
|
|
/// and text (<see cref="ZedGraph.Scale.IsText"/>) type axes.
|
|
/// </param>
|
|
/// <returns>The resulting value label as a <see cref="string" /></returns>
|
|
internal string MakeLabelEventWorks( GraphPane pane, int index, double dVal )
|
|
{
|
|
// if there is a valid ScaleFormatEvent, then try to use it to create the label
|
|
// the label will be non-null if it's to be used
|
|
if ( this.ScaleFormatEvent != null )
|
|
{
|
|
string label;
|
|
|
|
label = this.ScaleFormatEvent( pane, this, dVal, index );
|
|
if ( label != null )
|
|
return label;
|
|
}
|
|
|
|
// second try. If there's no custom ScaleFormatEvent, then just call
|
|
// _scale.MakeLabel according to the type of scale
|
|
if ( this.Scale != null )
|
|
return _scale.MakeLabel( pane, index, dVal );
|
|
else
|
|
return "?";
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
}
|
|
|