//============================================================================ //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 //============================================================================= #region Using directives using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Text; using System.Runtime.Serialization; using System.Security.Permissions; #endregion namespace DrawGraph { /// /// This class handles the drawing of the curve objects. /// The Hi-Low Bars are the "floating" bars that have a lower and upper value and /// appear at each defined point. /// /// /// John Champion /// $Revision: 3.17 $ $Date: 2007/04/16 00:03:02 $ [Serializable] public class HiLowBar : Bar, ICloneable, ISerializable { #region Fields /// /// Private field that stores the size (width) of this /// in points (1/72 inch). Use the public /// property to access this value. /// private float _size; /// /// Private field that determines whether the bar width will be based on /// the value, or it will be based on available /// space similar to objects. Use the public property /// to access this value. /// private bool _isAutoSize; /// /// The result of the autosize calculation, which is the size of the bars in /// user scale units. This is converted to pixels at draw time. /// internal double _userScaleSize = 1.0; #endregion #region Default /// /// A simple struct that defines the /// default property values for the class. /// new public struct Default { // Default HiLowBar properties /// /// The default size (width) for the bars ( property), /// in units of points. /// public static float Size = 7; /// /// Default value for the property. /// public static bool IsAutoSize = true; } #endregion #region Constructors /// /// Default constructor that sets all properties to default /// values as defined in the class. /// public HiLowBar() : this( Color.Empty ) { } /// /// Default constructor that sets the /// as specified, and the remaining /// properties to default /// values as defined in the class. /// The specified color is only applied to the /// , and the /// will be defaulted. /// /// A value indicating /// the /// of the Bar. /// public HiLowBar( Color color ) : this( color, Default.Size ) { } /// /// Default constructor that sets the /// and as specified, and the remaining /// properties to default /// values as defined in the class. /// The specified color is only applied to the /// , and the /// will be defaulted. /// /// A value indicating /// the /// of the Bar. /// /// The size (width) of the 's, in points /// (1/72nd inch) public HiLowBar( Color color, float size ) : base( color ) { _size = size; _isAutoSize = Default.IsAutoSize; } /// /// The Copy Constructor /// /// The object from which to copy public HiLowBar( HiLowBar rhs ) : base( rhs ) { _size = rhs._size; _isAutoSize = rhs._isAutoSize; } /// /// Implement the interface in a typesafe manner by just /// calling the typed version of /// /// A deep copy of this object object ICloneable.Clone() { return this.Clone(); } /// /// Typesafe, deep-copy clone method. /// /// A new, independent copy of this class new public HiLowBar Clone() { return new HiLowBar( this ); } #endregion #region Serialization /// /// Current schema value that defines the version of the serialized file /// public const int schema2 = 10; /// /// Constructor for deserializing objects /// /// A instance that defines the serialized data /// /// A instance that contains the serialized data /// protected HiLowBar( SerializationInfo info, StreamingContext context ) : base( info, 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( "schema2" ); _size = info.GetSingle( "size" ); _isAutoSize = info.GetBoolean( "isAutoSize" ); } /// /// Populates a instance with the data needed to serialize the target object /// /// A instance that defines the serialized data /// A instance that contains the serialized data [SecurityPermissionAttribute(SecurityAction.Demand,SerializationFormatter=true)] public override void GetObjectData( SerializationInfo info, StreamingContext context ) { base.GetObjectData( info, context ); info.AddValue( "schema2", schema2 ); info.AddValue( "size", _size ); info.AddValue( "isAutoSize", _isAutoSize ); } #endregion #region Properties /// /// Gets or sets the size of the /// /// The size of the bars can be set by this value, which /// is then scaled according to the scaleFactor (see /// ). Alternatively, /// if is true, the bar width will /// be set according to the maximum available cluster width less /// the cluster gap (see /// and ). That is, if /// is true, then the value of /// will be ignored. If you modify the value of Size, /// then will be automatically set to false. /// /// Size in points (1/72 inch) /// public float Size { get { return _size; } set { _size = value; _isAutoSize = false; } } /// /// Determines whether the bar width will be based on /// the value, or it will be based on available /// space similar to objects. /// /// If true, then the value of is ignored. /// If this value is true, then will be used to /// determine the total space between each bar. If the base axis is non-ordinal, then /// will be active. In this case, you may /// want to make sure that is true. /// public bool IsAutoSize { get { return _isAutoSize; } set { _isAutoSize = value; } } #endregion #region Methods /// /// Protected internal routine that draws the specified single bar (an individual "point") /// of this series to the specified device. /// /// /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// /// /// A reference to the object that is the parent or /// owner of this object. /// /// A object representing the /// 's to be drawn. /// /// The zero-based index number for the single bar to be drawn. /// /// /// The ordinal position of the this bar series (0=first bar, 1=second bar, etc.) /// in the cluster of bars. /// /// The class instance that defines the base (independent) /// axis for the /// The class instance that defines the value (dependent) /// axis for the /// /// The width of each bar, in pixels. /// /// /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent object using the /// method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// override protected void DrawSingleBar( Graphics g, GraphPane pane, CurveItem curve, int index, int pos, Axis baseAxis, Axis valueAxis, float barWidth, float scaleFactor ) { //float scaledSize = GetBarWidth( pane, baseAxis, scaleFactor ); // pixBase = pixel value for the bar center on the base axis // pixValue = pixel value for the bar top on the value axis // pixLow = pixel value for the bar bottom on the value axis float pixBase, pixHiVal, pixLowVal; // curBase = the scale value on the base axis of the current bar // curValue = the scale value on the value axis of the current bar double curBase, curLowVal, curHiVal; ValueHandler valueHandler = new ValueHandler( pane, false ); valueHandler.GetValues( curve, index, out curBase, out curLowVal, out curHiVal ); barWidth = GetBarWidth( pane, baseAxis, scaleFactor ); // curLow = the scale value on the value axis for the bottom of the current bar // Get a "low" value for the bottom of the bar and verify validity if ( curLowVal == PointPair.Missing || System.Double.IsNaN( curLowVal ) || System.Double.IsInfinity( curLowVal ) ) curLowVal = 0; // Any value set to double max is invalid and should be skipped // This is used for calculated values that are out of range, divide // by zero, etc. // Also, any value <= zero on a log scale is invalid if ( !curve.Points[index].IsInvalid ) { // calculate a pixel value for the top of the bar on value axis pixHiVal = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, index, curHiVal ); // calculate a pixel value for the center of the bar on the base axis pixBase = baseAxis.Scale.Transform( curve.IsOverrideOrdinal, index, curBase ); pixLowVal = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, index, curLowVal ); // Calculate the pixel location for the side of the bar (on the base axis) float pixSide = pixBase - barWidth / 2.0F; // Draw the bar if ( baseAxis is XAxis || baseAxis is X2Axis ) this.Draw( g, pane, pixSide, pixSide + barWidth, pixLowVal, pixHiVal, scaleFactor, true, curve.IsSelected, curve.Points[index] ); else this.Draw( g, pane, pixLowVal, pixHiVal, pixSide, pixSide + barWidth, scaleFactor, true, curve.IsSelected, curve.Points[index] ); } } /// /// Returns the width of the bar, in pixels, based on the settings for /// and . /// /// The parent object. /// The object that /// represents the bar base (independent axis). /// /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent object using the /// method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// /// The width of each bar, in pixel units public float GetBarWidth( GraphPane pane, Axis baseAxis, float scaleFactor ) { float width; if ( _isAutoSize ) width = baseAxis._scale.GetClusterWidth( _userScaleSize ) / ( 1.0F + pane._barSettings.MinClusterGap ); else width = (float) ( _size * scaleFactor ); // use integral size return (int)( width + 0.5f ); } #endregion } }