//============================================================================ //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.Runtime.Serialization; using System.Security.Permissions; #endregion namespace DrawGraph { /// /// Encapsulates an "High-Low" Bar curve type that displays a bar in which both /// the bottom and the top of the bar are set by data valuesfrom the /// struct. /// /// The type is intended for displaying /// bars that cover a band of data, such as a confidence interval, "waterfall" /// chart, etc. The width of the bar can be set in two ways. First, /// can be used to set a width in points (1/72nd inch), /// that is scaled using the regular scalefactor method (see /// ). In this manner, the bar widths /// are set similar to symbol sizes. The other method is to set /// to true, which will cause the bars /// to be scaled just like a in which only one /// bar series is present. That is, the bars width will be the width of /// a cluster less the clustergap (see /// and ). The position of each bar is set /// according to the values. The independent axis /// is assigned with , and is a /// enum type. If /// is set to or , then /// the bars will actually be horizontal, since the X axis becomes the /// value axis and the Y or Y2 axis becomes the independent axis. /// John Champion /// $Revision: 3.17 $ $Date: 2007/04/16 00:03:02 $ [Serializable] public class HiLowBarItem : CurveItem, ICloneable, ISerializable { #region Fields /// /// Private field that stores a reference to the /// class defined for this . Use the public /// property to access this value. /// private HiLowBar _bar; #endregion #region Constructors /// /// Create a new using the specified properties. /// /// The label that will appear in the legend. /// An array of double precision values that define /// the independent (X axis) values for this curve /// An array of double precision values that define /// the dependent (Y axis) values for this curve /// An array of double precision values that define the /// base value (the bottom) of the bars for this curve. /// /// A value that will be applied to /// the and properties. /// public HiLowBarItem( string label, double[] x, double[] y, double[] baseVal, Color color ) : this( label, new PointPairList( x, y, baseVal ), color ) { } /// /// Create a new using the specified properties. /// /// The label that will appear in the legend. /// A of double precision value trio's that define /// the X, Y, and lower dependent values for this curve /// A value that will be applied to /// the and properties. /// public HiLowBarItem( string label, IPointList points, Color color ) : base( label, points ) { _bar = new HiLowBar( color ); } /// /// The Copy Constructor /// /// The object from which to copy public HiLowBarItem( HiLowBarItem rhs ) : base( rhs ) { _bar = rhs._bar.Clone(); // new HiLowBar( rhs.Bar ); } /// /// 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 public HiLowBarItem Clone() { return new HiLowBarItem( 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 HiLowBarItem( 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" ); _bar = (HiLowBar) info.GetValue( "bar", typeof(HiLowBar) ); } /// /// 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( "bar", _bar ); } #endregion #region Properties /// /// Gets a reference to the class defined /// for this . /// public HiLowBar Bar { get { return _bar; } } /// /// Gets a flag indicating if the Z data range should be included in the axis scaling calculations. /// /// The parent of this . /// /// true if the Z data are included, false otherwise override internal bool IsZIncluded( GraphPane pane ) { return true; } /// /// Gets a flag indicating if the X axis is the independent axis for this /// /// The parent of this . /// /// true if the X axis is independent, false otherwise override internal bool IsXIndependent( GraphPane pane ) { return pane._barSettings.Base == BarBase.X; } #endregion #region Methods /// /// Do all rendering associated with this to the specified /// device. This method is normally only /// called by the Draw method of the parent /// collection object. /// /// /// 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. /// /// The ordinal position of the current /// curve. /// /// 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 public void Draw( Graphics g, GraphPane pane, int pos, float scaleFactor ) { if ( _isVisible ) _bar.DrawBars( g, pane, this, BaseAxis( pane ), ValueAxis( pane ), GetBarWidth( pane ), pos, scaleFactor ); } /// /// Draw a legend key entry for this at the specified location /// /// /// 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. /// /// The struct that specifies the /// location for the legend key /// /// 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 public void DrawLegendKey( Graphics g, GraphPane pane, RectangleF rect, float scaleFactor ) { _bar.Draw( g, pane, rect, scaleFactor, true, false, null ); } /// /// Determine the coords for the rectangle associated with a specified point for /// this /// /// The to which this curve belongs /// The index of the point of interest /// A list of coordinates that represents the "rect" for /// this point (used in an html AREA tag) /// true if it's a valid point, false otherwise override public bool GetCoords( GraphPane pane, int i, out string coords ) { coords = string.Empty; if ( i < 0 || i >= _points.Count ) return false; Axis valueAxis = ValueAxis( pane ); Axis baseAxis = BaseAxis( pane ); float scaledSize = GetBarWidth( pane ); // pixBase = pixel value for the bar center on the base axis // pixHiVal = pixel value for the bar top on the value axis // pixLowVal = pixel value for the bar bottom on the value axis float pixBase, pixHiVal, pixLowVal; float clusterWidth = pane.BarSettings.GetClusterWidth(); float barWidth = GetBarWidth( pane ); float clusterGap = pane._barSettings.MinClusterGap * barWidth; float barGap = barWidth * pane._barSettings.MinBarGap; // curBase = the scale value on the base axis of the current bar // curHiVal = the scale value on the value axis of the current bar // curLowVal = the scale value of the bottom of the bar double curBase, curLowVal, curHiVal; ValueHandler valueHandler = new ValueHandler( pane, false ); valueHandler.GetValues( this, i, out curBase, out curLowVal, out curHiVal ); // 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 ( !_points[i].IsInvalid3D ) { // calculate a pixel value for the top of the bar on value axis pixLowVal = valueAxis.Scale.Transform( _isOverrideOrdinal, i, curLowVal ); pixHiVal = valueAxis.Scale.Transform( _isOverrideOrdinal, i, curHiVal ); // calculate a pixel value for the center of the bar on the base axis pixBase = baseAxis.Scale.Transform( _isOverrideOrdinal, i, curBase ); // Calculate the pixel location for the side of the bar (on the base axis) float pixSide = pixBase - scaledSize / 2.0F; // Draw the bar if ( baseAxis is XAxis || baseAxis is X2Axis ) coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0}", pixSide, pixLowVal, pixSide + scaledSize, pixHiVal ); else coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0}", pixLowVal, pixSide, pixHiVal, pixSide + scaledSize ); return true; } return false; } #endregion } }