/// <summary> /// Construct a <see cref="ZoomState"/> object from the scale ranges settings contained /// in the specified <see cref="GraphPane"/>. /// </summary> /// <param name="pane">The <see cref="GraphPane"/> from which to obtain the scale /// range values. /// </param> /// <param name="type">A <see cref="StateType"/> enumeration that indicates whether /// this saved state is from a pan or zoom.</param> public ZoomState( GraphPane pane, StateType type ) { _xAxis = new ScaleState( pane.XAxis ); _x2Axis = new ScaleState( pane.X2Axis ); _yAxis = new ScaleStateList( pane.YAxisList ); _y2Axis = new ScaleStateList( pane.Y2AxisList ); _type = type; }
/// <summary> /// Basic constructor that saves a reference to the parent /// <see cref="GraphPane"/> object. /// </summary> /// <param name="pane">The parent <see cref="GraphPane"/> object.</param> /// <param name="initialize">A <see cref="bool"/> flag to indicate whether or /// not the drawing variables should be initialized. Initialization is not /// required if this is part of a ZedGraph internal draw operation (i.e., its in /// the middle of a call to <see cref="GraphPane.Draw"/>). Otherwise, you should /// initialize to make sure the drawing variables are configured. true to do /// an initialization, false otherwise.</param> public ValueHandler( GraphPane pane, bool initialize ) { _pane = pane; if ( initialize ) { // just create a dummy image, which results in a full draw operation using ( Image image = pane.GetImage() ) { } } }
/// <summary> /// Gets a flag indicating if the X axis is the independent axis for this <see cref="CurveItem" /> /// </summary> /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />. /// </param> /// <value>true if the X axis is independent, false otherwise</value> internal override bool IsXIndependent( GraphPane pane ) { return pane._barSettings.Base == BarBase.X; }
/// <summary> /// Draw a legend key entry for this <see cref="OHLCBarItem"/> at the specified location /// </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="rect">The <see cref="RectangleF"/> struct that specifies the /// location for the legend key</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 override void DrawLegendKey( Graphics g, GraphPane pane, RectangleF rect, float scaleFactor ) { float pixBase, pixHigh, pixLow, pixOpen, pixClose; if ( pane._barSettings.Base == BarBase.X ) { pixBase = rect.Left + rect.Width / 2.0F; pixHigh = rect.Top; pixLow = rect.Bottom; pixOpen = pixHigh + rect.Height / 3; pixClose = pixLow - rect.Height / 3; } else { pixBase = rect.Top + rect.Height / 2.0F; pixHigh = rect.Right; pixLow = rect.Left; pixOpen = pixHigh - rect.Width / 3; pixClose = pixLow + rect.Width / 3; } Axis baseAxis = BaseAxis( pane ); float halfSize = _stick.GetBarWidth( pane, baseAxis, scaleFactor ); using ( Pen pen = new Pen( _stick.Color, _stick._width ) ) { _stick.Draw( g, pane, pane._barSettings.Base == BarBase.X, pixBase, pixHigh, pixLow, pixOpen, pixClose, halfSize, scaleFactor, pen, _stick.RisingFill, _stick.RisingBorder, null ); } }
/// <summary> /// Gets a flag indicating if the Z data range should be included in the axis scaling calculations. /// </summary> /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />. /// </param> /// <value>true if the Z data are included, false otherwise</value> internal override bool IsZIncluded( GraphPane pane ) { return _symbol.IsVisible; }
/// <summary> /// Draw all the <see cref="ErrorBar"/>'s to the specified <see cref="Graphics"/> /// device as a an error bar at each defined point. /// </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="curve">A <see cref="CurveItem"/> object representing the /// <see cref="Bar"/>'s to be drawn.</param> /// <param name="baseAxis">The <see cref="Axis"/> class instance that defines the base (independent) /// axis for the <see cref="Bar"/></param> /// <param name="valueAxis">The <see cref="Axis"/> class instance that defines the value (dependent) /// axis for the <see cref="Bar"/></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 Draw( Graphics g, GraphPane pane, ErrorBarItem curve, Axis baseAxis, Axis valueAxis, float scaleFactor ) { ValueHandler valueHandler = new ValueHandler( pane, false ); float pixBase, pixValue, pixLowValue; double scaleBase, scaleValue, scaleLowValue; if ( curve.Points != null && this.IsVisible ) { using ( Pen pen = !curve.IsSelected ? new Pen( _color, _penWidth ) : new Pen( Selection.Border.Color, Selection.Border.Width ) ) { // Loop over each defined point for ( int i = 0; i < curve.Points.Count; i++ ) { valueHandler.GetValues( curve, i, out scaleBase, out scaleLowValue, out scaleValue ); // 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[i].IsInvalid3D && ( scaleBase > 0 || !baseAxis._scale.IsLog ) && ( ( scaleValue > 0 && scaleLowValue > 0 ) || !valueAxis._scale.IsLog ) ) { pixBase = baseAxis.Scale.Transform( curve.IsOverrideOrdinal, i, scaleBase ); pixValue = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, i, scaleValue ); pixLowValue = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, i, scaleLowValue ); //if ( this.fill.IsGradientValueType ) // brush = fill.MakeBrush( _rect, _points[i] ); this.Draw( g, pane, baseAxis is XAxis || baseAxis is X2Axis, pixBase, pixValue, pixLowValue, scaleFactor, pen, curve.IsSelected, curve.Points[i] ); } } } } }
/// <summary> /// Select a reasonable linear axis scale given a range of data values. /// </summary> /// <remarks> /// This method only applies to <see cref="AxisType.Linear"/> type axes, and it /// is called by the general <see cref="Scale.PickScale"/> method. The scale range is chosen /// based on increments of 1, 2, or 5 (because they are even divisors of 10). This /// method honors the <see cref="Scale.MinAuto"/>, <see cref="Scale.MaxAuto"/>, /// and <see cref="Scale.MajorStepAuto"/> autorange settings. /// In the event that any of the autorange settings are false, the /// corresponding <see cref="Scale.Min"/>, <see cref="Scale.Max"/>, or <see cref="Scale.MajorStep"/> /// setting is explicitly honored, and the remaining autorange settings (if any) will /// be calculated to accomodate the non-autoranged values. The basic defaults for /// scale selection are defined using <see cref="Scale.Default.ZeroLever"/>, /// <see cref="Scale.Default.TargetXSteps"/>, and <see cref="Scale.Default.TargetYSteps"/> /// from the <see cref="Scale.Default"/> default class. /// <para>On Exit:</para> /// <para><see cref="Scale.Min"/> is set to scale minimum (if <see cref="Scale.MinAuto"/> = true)</para> /// <para><see cref="Scale.Max"/> is set to scale maximum (if <see cref="Scale.MaxAuto"/> = true)</para> /// <para><see cref="Scale.MajorStep"/> is set to scale step size (if <see cref="Scale.MajorStepAuto"/> = true)</para> /// <para><see cref="Scale.MinorStep"/> is set to scale minor step size (if <see cref="Scale.MinorStepAuto"/> = true)</para> /// <para><see cref="Scale.Mag"/> is set to a magnitude multiplier according to the data</para> /// <para><see cref="Scale.Format"/> is set to the display format for the values (this controls the /// number of decimal places, whether there are thousands separators, currency types, etc.)</para> /// </remarks> /// <param name="pane">A reference to the <see cref="GraphPane"/> object /// associated with this <see cref="Axis"/></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> /// <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> /// <seealso cref="PickScale"/> /// <seealso cref="AxisType.Linear"/> public override void PickScale( GraphPane pane, Graphics g, float scaleFactor ) { // call the base class first base.PickScale( pane, g, scaleFactor ); // Test for trivial condition of range = 0 and pick a suitable default if ( _max - _min < 1.0e-30 ) { if ( _maxAuto ) _max = _max + 0.2 * ( _max == 0 ? 1.0 : Math.Abs( _max ) ); if ( _minAuto ) _min = _min - 0.2 * ( _min == 0 ? 1.0 : Math.Abs( _min ) ); } // This is the zero-lever test. If minVal is within the zero lever fraction // of the data range, then use zero. if ( _minAuto && _min > 0 && _min / ( _max - _min ) < Default.ZeroLever ) _min = 0; // Repeat the zero-lever test for cases where the maxVal is less than zero if ( _maxAuto && _max < 0 && Math.Abs( _max / ( _max - _min ) ) < Default.ZeroLever ) _max = 0; // Calculate the new step size if ( _majorStepAuto ) { double targetSteps = ( _ownerAxis is XAxis || _ownerAxis is X2Axis ) ? Default.TargetXSteps : Default.TargetYSteps; // Calculate the step size based on target steps _majorStep = CalcStepSize( _max - _min, targetSteps ); if ( _isPreventLabelOverlap ) { // Calculate the maximum number of labels double maxLabels = (double) this.CalcMaxLabels( g, pane, scaleFactor ); if ( maxLabels < ( _max - _min ) / _majorStep ) _majorStep = CalcBoundedStepSize( _max - _min, maxLabels ); } } // Calculate the new step size if ( _minorStepAuto ) _minorStep = CalcStepSize( _majorStep, ( _ownerAxis is XAxis || _ownerAxis is X2Axis ) ? Default.TargetMinorXSteps : Default.TargetMinorYSteps ); // Calculate the scale minimum if ( _minAuto ) _min = _min - MyMod( _min, _majorStep ); // Calculate the scale maximum if ( _maxAuto ) _max = MyMod( _max, _majorStep ) == 0.0 ? _max : _max + _majorStep - MyMod( _max, _majorStep ); SetScaleMag( _min, _max, _majorStep ); }
/// <summary> /// Make a value label for an <see cref="AxisType.Text" /> <see cref="Axis" />. /// </summary> /// <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="Scale.IsLog"/>) /// and text (<see cref="Scale.IsText"/>) type axes. /// </param> /// <returns>The resulting value label as a <see cref="string" /></returns> internal override string MakeLabel( GraphPane pane, int index, double dVal ) { if ( _format == null ) _format = Scale.Default.Format; index *= (int) _majorStep; if ( _textLabels == null || index < 0 || index >= _textLabels.Length ) return string.Empty; else return _textLabels[index]; }
/// <summary> /// The Copy Constructor /// </summary> /// <param name="rhs">The GraphPane object from which to copy</param> public GraphPane( GraphPane rhs ) : base(rhs) { // copy values for all the value types _isIgnoreInitial = rhs.IsIgnoreInitial; _isBoundedRanges = rhs._isBoundedRanges; _isAlignGrids = rhs._isAlignGrids; _chart = rhs._chart.Clone(); _barSettings = new BarSettings( rhs._barSettings, this ); _lineType = rhs.LineType; // copy all the reference types with deep copies _xAxis = new XAxis( rhs.XAxis ); _x2Axis = new X2Axis( rhs.X2Axis ); _yAxisList = new YAxisList( rhs._yAxisList ); _y2AxisList = new Y2AxisList( rhs._y2AxisList ); _curveList = new CurveList( rhs.CurveList ); _zoomStack = new ZoomStateStack( rhs._zoomStack ); }
/// <summary> /// Calculate the values needed to properly display this <see cref="PieItem"/>. /// </summary> /// <param name="pane"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="maxDisplacement">maximum slice displacement</param> private static void CalculatePieChartParams( GraphPane pane, ref double maxDisplacement ) { string lblStr = " "; //loop thru slices and get total value and maxDisplacement double pieTotalValue = 0; foreach ( PieItem curve in pane.CurveList ) if ( curve.IsPie ) { pieTotalValue += curve._pieValue; if ( curve.Displacement > maxDisplacement ) maxDisplacement = curve.Displacement; } double nextStartAngle = 0; //now loop thru and calculate the various angle values foreach ( PieItem curve in pane.CurveList ) { lblStr = curve._labelStr; curve.StartAngle = (float)nextStartAngle; curve.SweepAngle = (float)( 360 * curve.Value / pieTotalValue ); curve.MidAngle = curve.StartAngle + curve.SweepAngle / 2; nextStartAngle = curve._startAngle + curve._sweepAngle; PieItem.BuildLabelString( curve ); } }
/// <summary> /// Determine the coords for the rectangle associated with a specified point for /// this <see cref="CurveItem" /> /// </summary> /// <param name="pane">The <see cref="GraphPane" /> to which this curve belongs</param> /// <param name="i">The index of the point of interest</param> /// <param name="coords">A list of coordinates that represents the "rect" for /// this point (used in an html AREA tag)</param> /// <returns>true if it's a valid point, false otherwise</returns> public override bool GetCoords( GraphPane pane, int i, out string coords ) { coords = string.Empty; PointF pt = _boundingRectangle.Location; pt.X += _boundingRectangle.Width / 2.0f; pt.Y += _boundingRectangle.Height / 2.0f; float radius = _boundingRectangle.Width / 2.0f; Matrix matrix = new Matrix(); // Move the coordinate system to local coordinates // of this text object (that is, at the specified // x,y location) matrix.Translate( pt.X, pt.Y ); matrix.Rotate( this.StartAngle ); //One mark every 5'ish degrees int count = (int)Math.Floor ( SweepAngle / 5 ) + 1; PointF[] pts = new PointF[2 + count]; pts[0] = new PointF( 0, 0 ); pts[1] = new PointF( radius, 0 ); double angle = 0.0; for ( int j = 2; j < count + 2; j++ ) { angle += SweepAngle / count; pts[j] = new PointF(radius * (float)Math.Cos(angle * Math.PI / 180.0), radius * (float)Math.Sin( angle * Math.PI / 180.0 ) ); } matrix.TransformPoints( pts ); coords = String.Format("{0:f0},{1:f0},{2:f0},{3:f0},", pts[0].X, pts[0].Y, pts[1].X, pts[1].Y ); for (int j = 2; j < count + 2; j++) coords += String.Format(j > count ? "{0:f0},{1:f0}" : "{0:f0},{1:f0},", pts[j].X, pts[j].Y); return true; }
/// <summary> /// Draw a legend key entry for this <see cref="PieItem"/> at the specified location /// </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="rect">The <see cref="RectangleF"/> struct that specifies the /// location for the legend key</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 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 ); }
/// <summary> /// Render the label for this <see cref="PieItem"/>. /// </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 graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="rect">Bounding rectangle for this <see cref="PieItem"/>.</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 DrawLabel( Graphics g, GraphPane pane, RectangleF rect, float scaleFactor ) { if ( !_labelDetail.IsVisible ) return; using ( Pen labelPen = this.Border.GetPen( pane, scaleFactor ) ) { //draw line from intersection point to pivot point - g.DrawLine( labelPen, _intersectionPoint, _pivotPoint ); //draw horizontal line to move label away from pie... g.DrawLine( labelPen, _pivotPoint, _endPoint ); } //draw the label (TextObj) _labelDetail.Draw( g, pane, scaleFactor ); }
/// <summary> /// Do all rendering associated with this <see cref="PieItem"/> item to the specified /// <see cref="Graphics"/> device. This method is normally only /// called by the Draw method of the parent <see cref="CurveList"/> /// collection object. /// </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="pos">Not used for rendering Pies</param>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 override void Draw( Graphics g, GraphPane pane, int pos, float scaleFactor ) { if ( pane.Chart._rect.Width <= 0 && pane.Chart._rect.Height <= 0 ) { //pane.PieRect = RectangleF.Empty; _slicePath = null; } else { //pane.PieRect = CalcPieRect( g, pane, scaleFactor, pane.ChartRect ); CalcPieRect( 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; Fill tFill = _fill; Border tBorder = _border; if ( this.IsSelected ) { tFill = Selection.Fill; tBorder = Selection.Border; } using ( Brush brush = tFill.MakeBrush( _boundingRectangle ) ) { g.FillPie( brush, tRect.X, tRect.Y, tRect.Width, tRect.Height, this.StartAngle, this.SweepAngle ); //add GraphicsPath for hit testing _slicePath.AddPie( tRect.X, tRect.Y, tRect.Width, tRect.Height, this.StartAngle, this.SweepAngle ); if ( this.Border.IsVisible ) { using ( Pen borderPen = tBorder.GetPen( pane, scaleFactor ) ) { g.DrawPie( borderPen, tRect.X, tRect.Y, tRect.Width, tRect.Height, this.StartAngle, this.SweepAngle ); } } if ( _labelType != PieLabelType.None ) DrawLabel( g, pane, tRect, scaleFactor ); //brush.Dispose(); } g.SmoothingMode = sMode; } } }
/// <summary> /// This method collects all the data relative to rendering this <see cref="PieItem"/>'s label. /// </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 graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="rect">The rectangle used for rendering this <see cref="PieItem"/> /// </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 DesignLabel( Graphics g, GraphPane pane, RectangleF rect, float scaleFactor ) { if ( !_labelDetail.IsVisible ) return; _labelDetail.LayoutArea = new SizeF(); //this.labelDetail.IsWrapped = false; //label line will come off the explosion radius and then pivot to the horizontal right or left, //dependent on position.. //text will be at the end of horizontal segment... CalculateLinePoints( rect, _midAngle ); //now get size of bounding rect for label SizeF size = _labelDetail.FontSpec.BoundingBox( g, _labelStr, scaleFactor ); //how much room left for the label - most likely midangles for wrapping //Right - 315 -> 45 degrees //Bottom - 45 -> 135 //Left - 135 -> 225 //Top - 225 -> 315 RectangleF chartRect = pane.Chart._rect; float fill = 0; if ( _midAngle > 315 || _midAngle <= 45 ) { //correct by wrapping text fill = chartRect.X + chartRect.Width - _endPoint.X - 5; if ( size.Width > fill ) { //need to wrap, so create label rectangle for overloaded DrawString - two rows, max _labelDetail.LayoutArea = new SizeF( fill, size.Height * 3.0F ); } } if ( _midAngle > 45 && _midAngle <= 135 ) { //correct by moving radial line toward one or the other end of the range fill = chartRect.Y + chartRect.Height - _endPoint.Y - 5; //is there enuf room for the label if ( size.Height / 2 > fill ) { //no, so got to move explosion radius if ( _midAngle > 90 ) //move _label clockwise one-third of way to the end of the arc CalculateLinePoints( rect, _midAngle + ( _sweepAngle + _startAngle - _midAngle ) / 3 ); else //move _label counter-clockwise one-third of way to the start of the arc CalculateLinePoints( rect, _midAngle - ( _midAngle - ( _midAngle - _startAngle ) / 3 ) ); } } if ( _midAngle > 135 && _midAngle <= 225 ) { //wrap text fill = _endPoint.X - chartRect.X - 5; //need to wrap, so create label rectangle for overloaded DrawString - two rows, max if ( size.Width > fill ) { _labelDetail.LayoutArea = new SizeF( fill, size.Height * 3.0F ); } } if ( _midAngle > 225 && _midAngle <= 315 ) { //correct by moving radial line toward one or the other end of the range fill = _endPoint.Y - 5 - chartRect.Y; //is there enuf room for the label if ( size.Height / 2 > fill ) { //no, so got to move explosion radius if ( _midAngle < 270 ) //move _label counter-clockwise one-third of way to the start of the arc CalculateLinePoints( rect, _midAngle - ( _sweepAngle + _startAngle - _midAngle ) / 3 ); else //move _label clockwise one-third of way to the end of the arc CalculateLinePoints( rect, _midAngle + ( _midAngle - _startAngle ) / 3 ); } } //complete the location Detail info _labelDetail.Location.AlignV = AlignV.Center; _labelDetail.Location.CoordinateFrame = CoordType.PaneFraction; _labelDetail.Location.X = ( _endPoint.X - pane.Rect.X ) / pane.Rect.Width; _labelDetail.Location.Y = ( _endPoint.Y - pane.Rect.Y ) / pane.Rect.Height; _labelDetail.Text = _labelStr; }
/// <summary> /// Determine the coords for the rectangle associated with a specified point for /// this <see cref="CurveItem" /> /// </summary> /// <param name="pane">The <see cref="GraphPane" /> to which this curve belongs</param> /// <param name="i">The index of the point of interest</param> /// <param name="coords">A list of coordinates that represents the "rect" for /// this point (used in an html AREA tag)</param> /// <returns>true if it's a valid point, false otherwise</returns> public override bool GetCoords( GraphPane pane, int i, out string coords ) { coords = string.Empty; if ( i < 0 || i >= _points.Count ) return false; PointPair pt = _points[i]; if ( pt.IsInvalid ) return false; double x, y, z; ValueHandler valueHandler = new ValueHandler( pane, false ); valueHandler.GetValues( this, i, out x, out z, out y ); Axis yAxis = GetYAxis( pane ); Axis xAxis = GetXAxis( pane ); PointF pixPt = new PointF( xAxis.Scale.Transform( _isOverrideOrdinal, i, x ), yAxis.Scale.Transform( _isOverrideOrdinal, i, y ) ); if ( !pane.Chart.Rect.Contains( pixPt ) ) return false; float halfSize = _symbol.Size * pane.CalcScaleFactor(); coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0}", pixPt.X - halfSize, pixPt.Y - halfSize, pixPt.X + halfSize, pixPt.Y + halfSize ); return true; }
/// <summary> /// Select a reasonable text axis scale given a range of data values. /// </summary> /// <remarks> /// This method only applies to <see cref="AxisType.Text"/> type axes, and it /// is called by the general <see cref="PickScale"/> method. This is an ordinal /// type, such that the labeled values start at 1.0 and increment by 1.0 for /// each successive label. The maximum number of labels on the graph is /// determined by <see cref="Scale.Default.MaxTextLabels"/>. If necessary, this method will /// set the <see cref="Scale.MajorStep"/> value to greater than 1.0 in order to keep the total /// labels displayed below <see cref="Scale.Default.MaxTextLabels"/>. For example, a /// <see cref="Scale.MajorStep"/> size of 2.0 would only display every other label on the /// axis. The <see cref="Scale.MajorStep"/> value calculated by this routine is always /// an integral value. This /// method honors the <see cref="Scale.MinAuto"/>, <see cref="Scale.MaxAuto"/>, /// and <see cref="Scale.MajorStepAuto"/> autorange settings. /// In the event that any of the autorange settings are false, the /// corresponding <see cref="Scale.Min"/>, <see cref="Scale.Max"/>, or <see cref="Scale.MajorStep"/> /// setting is explicitly honored, and the remaining autorange settings (if any) will /// be calculated to accomodate the non-autoranged values. /// <para>On Exit:</para> /// <para><see cref="Scale.Min"/> is set to scale minimum (if <see cref="Scale.MinAuto"/> = true)</para> /// <para><see cref="Scale.Max"/> is set to scale maximum (if <see cref="Scale.MaxAuto"/> = true)</para> /// <para><see cref="Scale.MajorStep"/> is set to scale step size (if <see cref="Scale.MajorStepAuto"/> = true)</para> /// <para><see cref="Scale.MinorStep"/> is set to scale minor step size (if <see cref="Scale.MinorStepAuto"/> = true)</para> /// <para><see cref="Scale.Mag"/> is set to a magnitude multiplier according to the data</para> /// <para><see cref="Scale.Format"/> is set to the display format for the values (this controls the /// number of decimal places, whether there are thousands separators, currency types, etc.)</para> /// </remarks> /// <param name="pane">A reference to the <see cref="GraphPane"/> object /// associated with this <see cref="Axis"/></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> /// <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> /// <seealso cref="PickScale"/> /// <seealso cref="AxisType.Text"/> public override void PickScale( GraphPane pane, Graphics g, float scaleFactor ) { // call the base class first base.PickScale( pane, g, scaleFactor ); // if text labels are provided, then autorange to the number of labels if ( _textLabels != null ) { if ( _minAuto ) _min = 0.5; if ( _maxAuto ) _max = _textLabels.Length + 0.5; } else { if ( _minAuto ) _min -= 0.5; if ( _maxAuto ) _max += 0.5; } // Test for trivial condition of range = 0 and pick a suitable default if ( _max - _min < .1 ) { if ( _maxAuto ) _max = _min + 10.0; else _min = _max - 10.0; } if ( _majorStepAuto ) { if ( !_isPreventLabelOverlap ) { _majorStep = 1; } else if ( _textLabels != null ) { // Calculate the maximum number of labels double maxLabels = (double) this.CalcMaxLabels( g, pane, scaleFactor ); // Calculate a step size based on the width of the labels double tmpStep = Math.Ceiling( ( _max - _min ) / maxLabels ); // Use the lesser of the two step sizes //if ( tmpStep < this.majorStep ) _majorStep = tmpStep; } else _majorStep = (int) ( ( _max - _min - 1.0 ) / Default.MaxTextLabels ) + 1.0; } else { _majorStep = (int) _majorStep; if ( _majorStep <= 0 ) _majorStep = 1.0; } if ( _minorStepAuto ) { _minorStep = _majorStep / 10; //_minorStep = CalcStepSize( _majorStep, 10 ); if ( _minorStep < 1 ) _minorStep = 1; } _mag = 0; }
/// <summary> /// Calculate the <see cref="RectangleF"/> that will be used to define the bounding rectangle of /// the GasGaugeNeedle. /// </summary> /// <remarks>This rectangle always lies inside of the <see cref="Chart.Rect"/>, and it is /// normally a square so that the pie itself is not oval-shaped.</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="chartRect">The <see cref="RectangleF"/> (normally the <see cref="Chart.Rect"/>) /// that bounds this pie.</param> /// <returns></returns> 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.Inflate( -(float)0.05F * nonExpRect.Height, -(float)0.05 * nonExpRect.Width ); GasGaugeNeedle.CalculateGasGaugeParameters( pane ); foreach ( CurveItem curve in pane.CurveList ) { if ( curve is GasGaugeNeedle ) { GasGaugeNeedle ggn = (GasGaugeNeedle)curve; ggn._boundingRectangle = nonExpRect; } } return nonExpRect; }
/// <summary> /// Create a URL for a <see cref="CurveItem" /> that includes the index of the /// point that was selected. /// </summary> /// <remarks> /// An "index" parameter is added to the <see cref="Url" /> property for this /// link to indicate which point was selected. Further, if the /// X or Y axes that correspond to this <see cref="CurveItem" /> are of /// <see cref="AxisType.Text" />, then an /// additional parameter will be added containing the text value that /// corresponds to the <paramref name="index" /> of the selected point. /// The <see cref="XAxis" /> text parameter will be labeled "xtext", and /// the <see cref="YAxis" /> text parameter will be labeled "ytext". /// </remarks> /// <param name="index">The zero-based index of the selected point</param> /// <param name="pane">The <see cref="GraphPane" /> of interest</param> /// <param name="curve">The <see cref="CurveItem" /> for which to /// make the url string.</param> /// <returns>A string containing the url with an index parameter added.</returns> public virtual string MakeCurveItemUrl( GraphPane pane, CurveItem curve, int index ) { string url = _url; if ( url.IndexOf( '?' ) >= 0 ) url += "&index=" + index.ToString(); else url += "?index=" + index.ToString(); Axis xAxis = curve.GetXAxis( pane ); if ( xAxis.Type == AxisType.Text && index >= 0 && xAxis.Scale.TextLabels != null && index <= xAxis.Scale.TextLabels.Length ) url += "&xtext=" + xAxis.Scale.TextLabels[index]; Axis yAxis = curve.GetYAxis( pane ); if ( yAxis != null && yAxis.Type == AxisType.Text && index >= 0 && yAxis.Scale.TextLabels != null && index <= yAxis.Scale.TextLabels.Length ) url += "&ytext=" + yAxis.Scale.TextLabels[index]; return url; }
/// <summary> /// Calculate the values needed to properly display this <see cref="GasGaugeNeedle"/>. /// </summary> /// <param name="pane"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> public static void CalculateGasGaugeParameters( GraphPane pane ) { //loop thru slices and get total value and maxDisplacement double minVal = double.MaxValue; double maxVal = double.MinValue; 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; } //Set Needle Sweep angle values here based on the min and max values of the GasGuage foreach ( CurveItem curve in pane.CurveList ) { if ( curve is GasGaugeNeedle ) { GasGaugeNeedle ggn = (GasGaugeNeedle)curve; float sweep = ( (float)ggn.NeedleValue - (float)minVal ) / ( (float)maxVal - (float)minVal ) * 180.0f; ggn.SweepAngle = sweep; } } }
/// <summary> /// Draw the <see cref="ErrorBar"/> to the specified <see cref="Graphics"/> /// device at the specified location. /// </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="isXBase">boolean value that indicates if the "base" axis for this /// <see cref="ErrorBar"/> is the X axis. True for an <see cref="XAxis"/> base, /// false for a <see cref="YAxis"/> or <see cref="Y2Axis"/> base.</param> /// <param name="pixBase">The independent axis position of the center of the error bar in /// pixel units</param> /// <param name="pixValue">The dependent axis position of the top of the error bar in /// pixel units</param> /// <param name="pixLowValue">The dependent axis position of the bottom of the error bar in /// pixel units</param> /// <param name="scaleFactor"> /// The scaling factor for the features of the graph based on the <see cref="PaneBase.BaseDimension"/>. This /// scaling factor is calculated by the <see cref="PaneBase.CalcScaleFactor"/> method. The scale factor /// represents a linear multiple to be applied to font sizes, symbol sizes, etc.</param> /// <param name="pen">A pen with attributes of <see cref="Color"/> and /// <see cref="PenWidth"/> for this <see cref="ErrorBar"/></param> /// <param name="dataValue">The data value to be used for a value-based /// color gradient. This is only applicable for <see cref="FillType.GradientByX"/>, /// <see cref="FillType.GradientByY"/> or <see cref="FillType.GradientByZ"/>.</param> /// <param name="isSelected">Indicates that the <see cref="ErrorBar" /> should be drawn /// with attributes from the <see cref="Selection" /> class. /// </param> public void Draw( Graphics g, GraphPane pane, bool isXBase, float pixBase, float pixValue, float pixLowValue, float scaleFactor, Pen pen, bool isSelected, PointPair dataValue ) { if ( isXBase ) { g.DrawLine( pen, pixBase, pixValue, pixBase, pixLowValue ); _symbol.DrawSymbol( g, pane, (int)pixBase, (int)pixValue, scaleFactor, isSelected, dataValue ); _symbol.DrawSymbol( g, pane, (int)pixBase, (int)pixLowValue, scaleFactor, isSelected, dataValue ); } else { g.DrawLine( pen, pixValue, pixBase, pixLowValue, pixBase ); _symbol.DrawSymbol( g, pane, (int)pixValue, (int)pixBase, scaleFactor, isSelected, dataValue ); _symbol.DrawSymbol( g, pane, (int)pixLowValue, (int)pixBase, scaleFactor, isSelected, dataValue ); } }
/// <summary> /// Do all rendering associated with this <see cref="GasGaugeNeedle"/> item to the specified /// <see cref="Graphics"/> device. This method is normally only /// called by the Draw method of the parent <see cref="CurveList"/> /// collection object. /// </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="pos">Not used for rendering GasGaugeNeedle</param> /// <param name="scaleFactor">Not used for rendering GasGaugeNeedle</param> 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; Matrix matrix = new Matrix(); matrix.Translate( tRect.X + ( tRect.Width / 2 ), tRect.Y + ( tRect.Height / 2 ), MatrixOrder.Prepend ); PointF[] pts = new PointF[2]; pts[0] = new PointF( ( ( tRect.Height * .10f ) / 2.0f ) * (float)Math.Cos( -SweepAngle * Math.PI / 180.0f ), ( ( tRect.Height * .10f ) / 2.0f ) * (float)Math.Sin( -SweepAngle * Math.PI / 180.0f ) ); pts[1] = new PointF( ( tRect.Width / 2.0f ) * (float)Math.Cos( -SweepAngle * Math.PI / 180.0f ), ( tRect.Width / 2.0f ) * (float)Math.Sin( -SweepAngle * Math.PI / 180.0f ) ); matrix.TransformPoints( pts ); Pen p = new Pen( NeedleColor, ( ( tRect.Height * .10f ) / 2.0f ) ); p.EndCap = LineCap.ArrowAnchor; g.DrawLine( p, pts[0].X, pts[0].Y, pts[1].X, pts[1].Y ); //Fill center 10% with Black dot; Fill f = new Fill( Color.Black ); RectangleF r = new RectangleF( ( tRect.X + ( tRect.Width / 2 ) ) - 1.0f, ( tRect.Y + ( tRect.Height / 2 ) ) - 1.0f, 1.0f, 1.0f ); r.Inflate( ( tRect.Height * .10f ), ( tRect.Height * .10f ) ); Brush b = f.MakeBrush( r ); g.FillPie( b, r.X, r.Y, r.Width, r.Height, 0.0f, -180.0f ); Pen borderPen = new Pen( Color.White, 2.0f ); g.DrawPie( borderPen, r.X, r.Y, r.Width, r.Height, 0.0f, -180.0f ); g.SmoothingMode = sMode; } } }
/// <summary> /// Gets a flag indicating if the X axis is the independent axis for this <see cref="CurveItem" /> /// </summary> /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />. /// </param> /// <value>true if the X axis is independent, false otherwise</value> internal override bool IsXIndependent( GraphPane pane ) { return true; }
/// <summary> /// Render the label for this <see cref="GasGaugeNeedle"/>. /// </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 graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="rect">Bounding rectangle for this <see cref="GasGaugeNeedle"/>.</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 override void DrawLegendKey( Graphics g, GraphPane pane, RectangleF rect, float scaleFactor ) { if ( !_isVisible ) return; float yMid = rect.Top + rect.Height / 2.0F; Pen pen = new Pen( NeedleColor, pane.ScaledPenWidth( NeedleWidth / 2, scaleFactor ) ); pen.StartCap = LineCap.Round; pen.EndCap = LineCap.ArrowAnchor; pen.DashStyle = DashStyle.Solid; g.DrawLine( pen, rect.Left, yMid, rect.Right, yMid ); }
/// <summary> /// Do all rendering associated with this <see cref="OHLCBarItem"/> to the specified /// <see cref="Graphics"/> device. This method is normally only /// called by the Draw method of the parent <see cref="CurveList"/> /// collection object. /// </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="pos">The ordinal position of the current <see cref="OHLCBarItem"/> /// curve.</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 override void Draw( Graphics g, GraphPane pane, int pos, float scaleFactor ) { if ( _isVisible ) { _stick.Draw( g, pane, this, this.BaseAxis( pane ), this.ValueAxis( pane ), scaleFactor ); } }
/// <summary> /// Determine the coords for the rectangle associated with a specified point for /// this <see cref="CurveItem" /> /// </summary> /// <param name="pane">The <see cref="GraphPane" /> to which this curve belongs</param> /// <param name="i">The index of the point of interest</param> /// <param name="coords">A list of coordinates that represents the "rect" for /// this point (used in an html AREA tag)</param> /// <returns>true if it's a valid point, false otherwise</returns> public override bool GetCoords( GraphPane pane, int i, out string coords ) { coords = String.Empty; return false; }
/// <summary> /// Determine the coords for the rectangle associated with a specified point for /// this <see cref="CurveItem" /> /// </summary> /// <param name="pane">The <see cref="GraphPane" /> to which this curve belongs</param> /// <param name="i">The index of the point of interest</param> /// <param name="coords">A list of coordinates that represents the "rect" for /// this point (used in an html AREA tag)</param> /// <returns>true if it's a valid point, false otherwise</returns> public override 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 halfSize = _stick.Size * pane.CalcScaleFactor(); PointPair pt = _points[i]; double date = pt.X; double high = pt.Y; double low = pt.Z; if ( !pt.IsInvalid3D && ( date > 0 || !baseAxis._scale.IsLog ) && ( ( high > 0 && low > 0 ) || !valueAxis._scale.IsLog ) ) { float pixBase, pixHigh, pixLow; pixBase = baseAxis.Scale.Transform( _isOverrideOrdinal, i, date ); pixHigh = valueAxis.Scale.Transform( _isOverrideOrdinal, i, high ); pixLow = valueAxis.Scale.Transform( _isOverrideOrdinal, i, low ); // Calculate the pixel location for the side of the bar (on the base axis) float pixSide = pixBase - halfSize; // Draw the bar if ( baseAxis is XAxis || baseAxis is X2Axis ) coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0}", pixSide, pixLow, pixSide + halfSize * 2, pixHigh ); else coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0}", pixLow, pixSide, pixHigh, pixSide + halfSize * 2 ); return true; } return false; }
/// <summary> /// Do all rendering associated with this <see cref="LineItem"/> to the specified /// <see cref="Graphics"/> device. This method is normally only /// called by the Draw method of the parent <see cref="CurveList"/> /// collection object. /// </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="pos">The ordinal position of the current <see cref="Bar"/> /// curve.</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 override void Draw( Graphics g, GraphPane pane, int pos, float scaleFactor ) { if ( _isVisible ) { Line.Draw( g, pane, this, scaleFactor ); Symbol.Draw( g, pane, this, scaleFactor, IsSelected ); } }
/// <summary> /// Gets a flag indicating if the Z data range should be included in the axis scaling calculations. /// </summary> /// <remarks> /// IsZIncluded is true for <see cref="JapaneseCandleStickItem" /> objects, since the Y and Z /// values are defined as the High and Low values for the day.</remarks> /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />. /// </param> /// <value>true if the Z data are included, false otherwise</value> internal override bool IsZIncluded( GraphPane pane ) { return true; }
/// <summary> /// Draw a legend key entry for this <see cref="LineItem"/> at the specified location /// </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="rect">The <see cref="RectangleF"/> struct that specifies the /// location for the legend key</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 override void DrawLegendKey( Graphics g, GraphPane pane, RectangleF rect, float scaleFactor ) { // Draw a sample curve to the left of the label text int xMid = (int)( rect.Left + rect.Width / 2.0F ); int yMid = (int) (rect.Top + rect.Height / 2.0F); //RectangleF rect2 = rect; //rect2.Y = yMid; //rect2.Height = rect.Height / 2.0f; _line.Fill.Draw( g, rect ); _line.DrawSegment( g, pane, rect.Left, yMid, rect.Right, yMid, scaleFactor ); // Draw a sample symbol to the left of the label text _symbol.DrawSymbol( g, pane, xMid, yMid, scaleFactor, false, null ); }