//============================================================================ //GasGaugeRegion Class //Copyright ?2006 Jay Mistry // //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.Runtime.Serialization; using System.Drawing.Drawing2D; using System; using System.Text; using System.Drawing; using System.Security.Permissions; namespace DrawGraph { /// /// A class representing a region on the GasGuage chart /// s. /// /// Jay Mistry /// $Revision: 1.1 $ $Date: 2007/04/29 02:07:03 $ [Serializable] public class GasGaugeRegion : CurveItem, ICloneable, ISerializable { #region Fields /// /// Defines the minimum value of this /// private double _minValue; /// /// Defines the maximum value of this /// private double _maxValue; /// /// Defines the Color of this /// private Color _color; /// /// Internally calculated; Start angle of this pie that defines this /// private float _startAngle; /// /// Internally calculated; Sweep angle of this pie that defines this /// private float _sweepAngle; /// /// Private field that stores the data for this /// . Use the public property to /// access this value. /// private Fill _fill; /// /// A which will customize the label display of this /// /// private TextObj _labelDetail; /// /// Private field that stores the class that defines the /// properties of the border around this . Use the public /// property to access this value. /// private Border _border; /// /// The bounding rectangle for this . /// private RectangleF _boundingRectangle; /// /// Private field to hold the GraphicsPath of this to be /// used for 'hit testing'. /// private GraphicsPath _slicePath; #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 GasGaugeRegion( 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" ); _labelDetail = (TextObj)info.GetValue( "labelDetail", typeof( TextObj ) ); _fill = (Fill)info.GetValue( "fill", typeof( Fill ) ); _border = (Border)info.GetValue( "border", typeof( Border ) ); _color = (Color)info.GetValue( "color", typeof( Color ) ); _minValue = info.GetDouble( "minValue" ); _maxValue = info.GetDouble( "maxValue" ); _startAngle = (float)info.GetDouble( "startAngle" ); _sweepAngle = (float)info.GetDouble( "sweepAngle" ); _boundingRectangle = (RectangleF)info.GetValue( "boundingRectangle", typeof( RectangleF ) ); _slicePath = (GraphicsPath)info.GetValue( "slicePath", typeof( GraphicsPath ) ); } /// /// 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( "labelDetail", _labelDetail ); info.AddValue( "fill", _fill ); info.AddValue( "color", _color ); info.AddValue( "border", _border ); info.AddValue( "minVal", _minValue ); info.AddValue( "maxVal", _maxValue ); info.AddValue( "startAngle", _startAngle ); info.AddValue( "sweepAngle", _sweepAngle ); info.AddValue( "boundingRectangle", _boundingRectangle ); info.AddValue( "slicePath", _slicePath ); } #endregion #region Constructors /// /// Create a new /// /// The value associated with this instance. /// The display color for this instance. /// The minimum value of this . /// The maximum value of this . public GasGaugeRegion( string label, double minVal, double maxVal, Color color ) : base( label ) { MinValue = minVal; MaxValue = maxVal; RegionColor = color; StartAngle = 0f; SweepAngle = 0f; _border = new Border( Default.BorderColor, Default.BorderWidth ); _labelDetail = new TextObj(); _labelDetail.FontSpec.Size = Default.FontSize; _slicePath = null; } /// /// The Copy Constructor /// /// The object from which to copy public GasGaugeRegion( GasGaugeRegion ggr ) : base( ggr ) { _minValue = ggr._minValue; _maxValue = ggr._maxValue; _color = ggr._color; _startAngle = ggr._startAngle; _sweepAngle = ggr._sweepAngle; _border = ggr._border.Clone(); _labelDetail = ggr._labelDetail.Clone(); } /// /// 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 GasGaugeRegion Clone() { return new GasGaugeRegion( this ); } #endregion #region Properties /// /// Gets or sets the SlicePath of this /// public GraphicsPath SlicePath { get { return _slicePath; } } /// /// Gets or sets the LabelDetail of this /// public TextObj LabelDetail { get { return _labelDetail; } set { _labelDetail = value; } } /// /// Gets or sets the Border of this /// public Border Border { get { return ( _border ); } set { _border = value; } } /// /// Gets or sets the RegionColor of this /// public Color RegionColor { get { return _color; } set { _color = value; Fill = new Fill( _color ); } } /// /// Gets or sets the Fill of this /// public Fill Fill { get { return _fill; } set { _fill = value; } } /// /// Gets or sets the SweepAngle of this /// private float SweepAngle { get { return _sweepAngle; } set { _sweepAngle = value; } } /// /// Gets or sets the StartAngle of this /// private float StartAngle { get { return ( _startAngle ); } set { _startAngle = value; } } /// /// Gets or sets the MinValue of this /// public double MinValue { get { return ( _minValue ); } set { _minValue = value > 0 ? value : 0; } } /// /// Gets or sets the MaxValue of this /// public double MaxValue { get { return ( _maxValue ); } set { _maxValue = value > 0 ? value : 0; } } /// /// 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 false; } /// /// 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 true; } #endregion #region Defaults /// /// Specify the default property values for the class. /// public struct Default { /// /// The default border pen width for the /// public static float BorderWidth = 1.0F; /// /// The default fill type for the /// public static FillType FillType = FillType.Brush; /// /// The default value for the visibility of the border. /// public static bool IsBorderVisible = true; /// /// The default value for the color of the border /// public static Color BorderColor = Color.Gray; /// /// The default value for the color of the fill /// public static Color FillColor = Color.Empty; /// /// The default value for the fill brush of the /// public static Brush FillBrush = null; /// /// The default value for the visibility of the fill. /// public static bool isVisible = true; // public static PieLabelType LabelType = PieLabelType.Name; /// /// The default value for the font size of the labels. /// public static float FontSize = 10; } #endregion Defaults #region Methods /// /// Do all rendering associated with this item 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. /// /// Not used for rendering GasGaugeNeedle /// /// 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. /// public override void Draw( Graphics g, GraphPane pane, int pos, float scaleFactor ) { if ( pane.Chart._rect.Width <= 0 && pane.Chart._rect.Height <= 0 ) { _slicePath = null; } else { CalcRectangle( g, pane, scaleFactor, pane.Chart._rect ); _slicePath = new GraphicsPath(); if ( !_isVisible ) return; RectangleF tRect = _boundingRectangle; if ( tRect.Width >= 1 && tRect.Height >= 1 ) { SmoothingMode sMode = g.SmoothingMode; g.SmoothingMode = SmoothingMode.AntiAlias; _slicePath.AddPie( tRect.X, tRect.Y, tRect.Width, tRect.Height, -0.0f, -180.0f ); g.FillPie( Fill.MakeBrush( _boundingRectangle ), tRect.X, tRect.Y, tRect.Width, tRect.Height, -StartAngle, -SweepAngle ); if ( this.Border.IsVisible ) { Pen borderPen = _border.GetPen( pane, scaleFactor ); g.DrawPie( borderPen, tRect.X, tRect.Y, tRect.Width, tRect.Height, -0.0f, -180.0f ); borderPen.Dispose(); } g.SmoothingMode = sMode; } } } /// /// Render the label for this . /// /// /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// /// /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// /// Bounding rectangle for this . /// /// 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. /// public override void DrawLegendKey( Graphics g, GraphPane pane, RectangleF rect, float scaleFactor ) { if ( !_isVisible ) return; // Fill the slice if ( _fill.IsVisible ) { // just avoid height/width being less than 0.1 so GDI+ doesn't cry using ( Brush brush = _fill.MakeBrush( rect ) ) { g.FillRectangle( brush, rect ); //brush.Dispose(); } } // Border the bar if ( !_border.Color.IsEmpty ) _border.Draw( g, pane, scaleFactor, rect ); } /// /// 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 public override bool GetCoords( GraphPane pane, int i, out string coords ) { coords = String.Empty; return false; } /// /// Calculate the values needed to properly display this . /// /// /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// public static void CalculateGasGuageParameters( GraphPane pane ) { //loop thru slices and get total value and maxDisplacement double minVal = 0; double maxVal = 0; foreach ( CurveItem curve in pane.CurveList ) if ( curve is GasGaugeRegion ) { GasGaugeRegion ggr = (GasGaugeRegion)curve; if ( maxVal < ggr.MaxValue ) maxVal = ggr.MaxValue; if ( minVal > ggr.MinValue ) minVal = ggr.MinValue; } //Calculate start and sweep angles for each of the GasGaugeRegion based on teh min and max value foreach ( CurveItem curve in pane.CurveList ) { if ( curve is GasGaugeRegion ) { GasGaugeRegion ggr = (GasGaugeRegion)curve; float start = ( ( (float)ggr.MinValue ) - ( (float)minVal ) ) / ( (float)maxVal ) * 180.0f; float sweep = ( ( (float)ggr.MaxValue ) - ( (float)minVal ) ) / ( (float)maxVal ) * 180.0f; sweep = sweep - start; Fill f = new Fill( Color.White, ggr.RegionColor, -( sweep / 2f ) ); ggr.Fill = f; ggr.StartAngle = start; ggr.SweepAngle = sweep; } } } /// /// Calculate the that will be used to define the bounding rectangle of /// the GasGaugeNeedle. /// /// This rectangle always lies inside of the , and it is /// normally a square so that the pie itself is not oval-shaped. /// /// 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 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 (normally the ) /// that bounds this pie. /// public static RectangleF CalcRectangle( Graphics g, GraphPane pane, float scaleFactor, RectangleF chartRect ) { RectangleF nonExpRect = chartRect; if ( ( 2 * nonExpRect.Height ) > nonExpRect.Width ) { //Scale based on width float percentS = ( ( nonExpRect.Height * 2 ) - nonExpRect.Width ) / ( nonExpRect.Height * 2 ); nonExpRect.Height = ( ( nonExpRect.Height * 2 ) - ( ( nonExpRect.Height * 2 ) * percentS ) ); } else { nonExpRect.Height = nonExpRect.Height * 2; } nonExpRect.Width = nonExpRect.Height; float xDelta = ( chartRect.Width / 2 ) - ( nonExpRect.Width / 2 ); //Align Horizontally nonExpRect.X += xDelta; //nonExpRect.Y += -(float)0.025F * nonExpRect.Height; //nonExpRect.Y += ((chartRect.Height) - (nonExpRect.Height / 2)) - 10.0f; nonExpRect.Inflate( -(float)0.05F * nonExpRect.Height, -(float)0.05 * nonExpRect.Width ); GasGaugeRegion.CalculateGasGuageParameters( pane ); foreach ( CurveItem curve in pane.CurveList ) { if ( curve is GasGaugeRegion ) { GasGaugeRegion gg = (GasGaugeRegion)curve; gg._boundingRectangle = nonExpRect; } } return nonExpRect; } #endregion } }