//============================================================================ //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 { /// /// Encapsulates an "Error Bar" curve type that displays a vertical or horizontal /// line with a symbol at each end. /// /// The type is intended for displaying /// confidence intervals, candlesticks, stock High-Low charts, etc. It is /// technically not a bar, since it is drawn as a vertical or horizontal line. /// The default symbol at each end of the "bar" is , /// which creates an "I-Beam". For horizontal bars /// ( or /// ), you will need to change the symbol to /// to get horizontal "I-Beams". /// Since the horizontal segments are actually symbols, their widths are /// controlled by the symbol size in , /// specified in points (1/72nd inch). The position of each "I-Beam" is set /// according to the values. The independent axis /// is assigned with , and is a /// enum type. /// John Champion /// $Revision: 3.19 $ $Date: 2007/04/16 00:03:01 $ [Serializable] public class ErrorBarItem : 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 ErrorBar _bar; #endregion #region Properties /// /// Gets a reference to the class defined /// for this . /// public ErrorBar 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 Constructors /// /// Create a new , specifying only the legend label. /// /// The label that will appear in the legend. public ErrorBarItem( string label ) : base( label ) { _bar = new ErrorBar(); } /// /// Create a new using the specified properties. /// /// The label that will appear in the legend. /// An array of double precision values that define /// the X axis values for this curve /// An array of double precision values that define /// the Y axis values for this curve /// An array of double precision values that define /// the lower dependent values for this curve /// A value that will be applied to /// the properties. /// public ErrorBarItem( string label, double[] x, double[] y, double[] lowValue, System.Drawing.Color color ) : this( label, new PointPairList( x, y, lowValue ), color ) { } /// /// Create a new using the specified properties. /// /// The label that will appear in the legend. /// A of double precision values that define /// the X, Y and lower dependent values for this curve /// A value that will be applied to /// the properties. /// public ErrorBarItem( string label, IPointList points, Color color ) : base( label, points ) { _bar = new ErrorBar( color ); } /// /// The Copy Constructor /// /// The object from which to copy public ErrorBarItem( ErrorBarItem rhs ) : base( rhs ) { _bar = new ErrorBar( 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 ErrorBarItem Clone() { return new ErrorBarItem( 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 ErrorBarItem( 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 = (ErrorBar) info.GetValue( "bar", typeof(ErrorBar) ); // This is now just a dummy variable, since barBase was removed BarBase barBase = (BarBase) info.GetValue( "barBase", typeof(BarBase) ); } /// /// 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 ); // BarBase is now just a dummy value, since the GraphPane.BarBase is used exclusively info.AddValue( "barBase", 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.Draw( g, pane, this, this.BaseAxis( pane ), this.ValueAxis( pane ), 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 ) { float pixBase, pixValue, pixLowValue; if ( pane._barSettings.Base == BarBase.X ) { pixBase = rect.Left + rect.Width / 2.0F; pixValue = rect.Top; pixLowValue = rect.Bottom; } else { pixBase = rect.Top + rect.Height / 2.0F; pixValue = rect.Right; pixLowValue = rect.Left; } using ( Pen pen = new Pen( _bar.Color, _bar.PenWidth ) ) { this.Bar.Draw( g, pane, pane._barSettings.Base == BarBase.X, pixBase, pixValue, pixLowValue, scaleFactor, pen, 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 = _bar.Symbol.Size * pane.CalcScaleFactor(); // 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 } }