/// <summary> /// Determines the shape type and Coords values for this GraphObj /// </summary> override public void GetCoords( PaneBase pane, Graphics g, float scaleFactor, out string shape, out string coords ) { // transform the x,y location from the user-defined // coordinate frame to the screen pixel location RectangleF pixRect = _location.TransformRect( pane ); shape = "rect"; coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0}", pixRect.Left, pixRect.Top, pixRect.Right, pixRect.Bottom ); }
/// <summary> /// Transform the <see c_ref="RectangleF"/> for this object as defined by the /// <see c_ref="X"/>, <see c_ref="Y"/>, <see c_ref="Width"/>, and /// <see c_ref="Height"/> properties. /// </summary> /// <remarks> /// This method transforms the location to output device pixel units. /// The <see c_ref="AlignH"/> and <see c_ref="AlignV"/> properties are honored in /// this transformation. /// </remarks> /// <value>A <see c_ref="RectangleF"/> in pixel units.</value> public RectangleF TransformRect( PaneBase pane ) { PointF pix1 = TransformTopLeft( pane ); PointF pix2 = TransformBottomRight( pane ); //PointF pix3 = TransformTopLeft( pane, pix2.X - pix1.X, pix2.Y - pix1.Y ); return new RectangleF( pix1.X, pix1.Y, Math.Abs(pix2.X - pix1.X), Math.Abs(pix2.Y - pix1.Y) ); }
/// <summary> /// Render the specified <paramref name="text"/> to the specifed /// <see c_ref="Graphics"/> device. The text, border, and fill options /// will be rendered as required. /// </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 c_ref="PaneBase"/> object that is the parent or /// owner of this object. /// </param> /// <param name="text">A string value containing the text to be /// displayed. This can be multiple lines, separated by newline ('\n') /// characters</param> /// <param name="x">The X location to display the text, in screen /// coordinates, relative to the horizontal (<see c_ref="AlignH"/>) /// alignment parameter <paramref name="alignH"/></param> /// <param name="y">The Y location to display the text, in screen /// coordinates, relative to the vertical (<see c_ref="AlignV"/> /// alignment parameter <paramref name="alignV"/></param> /// <param name="alignH">A horizontal alignment parameter specified /// using the <see c_ref="AlignH"/> enum type</param> /// <param name="alignV">A vertical alignment parameter specified /// using the <see c_ref="AlignV"/> enum type</param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see c_ref="GraphPane"/> object using the /// <see c_ref="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, PaneBase pane, string text, float x, float y, AlignH alignH, AlignV alignV, float scaleFactor ) { Draw( g, pane, text, x, y, alignH, alignV, scaleFactor, new SizeF() ); }
/// <summary> /// Transform a data point from the specified coordinate type /// (<see c_ref="CoordType"/>) to display device coordinates (pixels). /// </summary> /// <remarks> /// If <see paramref="pane"/> is not of type <see c_ref="GraphPane"/>, then /// only the <see c_ref="CoordType.PaneFraction"/> transformation is available. /// </remarks> /// <param name="pane"> /// A reference to the <see c_ref="PaneBase"/> object that contains /// the <see c_ref="Axis"/> classes which will be used for the transform. /// </param> /// <param name="x">The x coordinate that defines the point in user /// space.</param> /// <param name="y">The y coordinate that defines the point in user /// space.</param> /// <param name="coord">A <see c_ref="CoordType"/> type that defines the /// coordinate system in which the X,Y pair is defined.</param> /// <returns>A point in display device coordinates that corresponds to the /// specified user point.</returns> public static PointF Transform( PaneBase pane, double x, double y, CoordType coord ) { return pane.TransformCoord( x, y, coord ); }
/// <summary> /// The <see c_ref="PointF"/> for this object as defined by the /// <see c_ref="X"/> and <see c_ref="Y"/> /// properties. /// </summary> /// <remarks> /// This method transforms the location to output device pixel units. /// The <see c_ref="AlignH"/> and <see c_ref="AlignV"/> properties are ignored for /// this transformation (see <see c_ref="TransformTopLeft(PaneBase,float,float)"/>). /// </remarks> /// <value>A <see c_ref="PointF"/> in pixel units.</value> public PointF TransformTopLeft( PaneBase pane ) { return Transform( pane ); }
/// <summary> /// Determine if the specified screen point lies inside the bounding box of this /// <see c_ref="GraphObj"/>. /// </summary> /// <param name="pt">The screen point, in pixels</param> /// <param name="pane"> /// A reference to the <see c_ref="PaneBase"/> object that is the parent or /// owner of this object. /// </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 c_ref="PaneBase"/> object using the /// <see c_ref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <returns>true if the point lies in the bounding box, false otherwise</returns> virtual public bool PointInBox( PointF pt, PaneBase pane, Graphics g, float scaleFactor ) { GraphPane gPane = pane as GraphPane; if ( gPane != null && _isClippedToChartRect && !gPane.Chart.Rect.Contains( pt ) ) return false; return true; }
/// <summary> /// Render this object to the specified <see c_ref="Graphics"/> device. /// </summary> /// <remarks> /// This method is normally only called by the Draw method /// of the parent <see c_ref="GraphObjList"/> collection object. /// </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 c_ref="PaneBase"/> 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 c_ref="GraphPane"/> object using the /// <see c_ref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> override public void Draw( Graphics g, PaneBase pane, float scaleFactor ) { // Convert the arrow coordinates from the user coordinate system // to the screen coordinate system PointF pix1 = Location.TransformTopLeft( pane ); PointF pix2 = Location.TransformBottomRight( pane ); if ( pix1.X > -10000 && pix1.X < 100000 && pix1.Y > -100000 && pix1.Y < 100000 && pix2.X > -10000 && pix2.X < 100000 && pix2.Y > -100000 && pix2.Y < 100000 ) { // get a scaled size for the arrowhead float scaledSize = _size * scaleFactor; // calculate the length and the angle of the arrow "vector" double dy = pix2.Y - pix1.Y; double dx = pix2.X - pix1.X; float angle = (float)Math.Atan2( dy, dx ) * 180.0F / (float)Math.PI; float length = (float)Math.Sqrt( dx * dx + dy * dy ); // Save the old transform matrix Matrix transform = g.Transform; // Move the coordinate system so it is located at the starting point // of this arrow g.TranslateTransform( pix1.X, pix1.Y ); // Rotate the coordinate system according to the angle of this arrow // about the starting point g.RotateTransform( angle ); // get a pen according to this arrow properties using ( Pen pen = _line.GetPen( pane, scaleFactor ) ) //new Pen( _color, pane.ScaledPenWidth( _penWidth, scaleFactor ) ) ) { //pen.DashStyle = _style; // Only show the arrowhead if required if ( _isArrowHead ) { // Draw the line segment for this arrow g.DrawLine( pen, 0, 0, length - scaledSize + 1, 0 ); // Create a polygon representing the arrowhead based on the scaled // size PointF[] polyPt = new PointF[4]; float hsize = scaledSize / 3.0F; polyPt[0].X = length; polyPt[0].Y = 0; polyPt[1].X = length - scaledSize; polyPt[1].Y = hsize; polyPt[2].X = length - scaledSize; polyPt[2].Y = -hsize; polyPt[3] = polyPt[0]; using ( SolidBrush brush = new SolidBrush( _line._color ) ) // render the arrowhead g.FillPolygon( brush, polyPt ); } else g.DrawLine( pen, 0, 0, length, 0 ); } // Restore the transform matrix back to its original state g.Transform = transform; } }
/// <summary> /// Determines the shape type and Coords values for this GraphObj /// </summary> override public void GetCoords( PaneBase pane, Graphics g, float scaleFactor, out string shape, out string coords ) { // transform the x,y location from the user-defined // coordinate frame to the screen pixel location PointF pix = _location.Transform( pane ); PointF[] pts = _fontSpec.GetBox( g, _text, pix.X, pix.Y, _location.AlignH, _location.AlignV, scaleFactor, new SizeF() ); shape = "poly"; coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0},{4:f0},{5:f0},{6:f0},{7:f0},", pts[0].X, pts[0].Y, pts[1].X, pts[1].Y, pts[2].X, pts[2].Y, pts[3].X, pts[3].Y ); }
/// <summary> /// Render this object to the specified <see c_ref="Graphics"/> device. /// </summary> /// <remarks> /// This method is normally only called by the Draw method /// of the parent <see c_ref="GraphObjList"/> collection object. /// </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 c_ref="PaneBase"/> 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 c_ref="GraphPane"/> object using the /// <see c_ref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> override public void Draw( Graphics g, PaneBase pane, float scaleFactor ) { // Convert the arrow coordinates from the user coordinate system // to the screen coordinate system PointF pix1 = Location.TransformTopLeft( pane ); PointF pix2 = Location.TransformBottomRight( pane ); if ( pix1.X > -10000 && pix1.X < 100000 && pix1.Y > -100000 && pix1.Y < 100000 && pix2.X > -10000 && pix2.X < 100000 && pix2.Y > -100000 && pix2.Y < 100000 ) { // calculate the length and the angle of the arrow "vector" double dy = pix2.Y - pix1.Y; double dx = pix2.X - pix1.X; float angle = (float)Math.Atan2( dy, dx ) * 180.0F / (float)Math.PI; float length = (float)Math.Sqrt( dx * dx + dy * dy ); // Save the old transform matrix Matrix transform = g.Transform; // Move the coordinate system so it is located at the starting point // of this arrow g.TranslateTransform( pix1.X, pix1.Y ); // Rotate the coordinate system according to the angle of this arrow // about the starting point g.RotateTransform( angle ); // get a pen according to this arrow properties using ( Pen pen = _line.GetPen( pane, scaleFactor ) ) //new Pen( _line._color, pane.ScaledPenWidth( _line._width, scaleFactor ) ) ) { //pen.DashStyle = _style; g.DrawLine( pen, 0, 0, length, 0 ); } // Restore the transform matrix back to its original state g.Transform = transform; } }
/// <summary> /// Render this <see c_ref="TextObj"/> object to the specified <see c_ref="Graphics"/> device /// This method is normally only called by the Draw method /// of the parent <see c_ref="GraphObjList"/> 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 c_ref="PaneBase"/> 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 c_ref="GraphPane"/> object using the /// <see c_ref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> override public void Draw( Graphics g, PaneBase pane, float scaleFactor ) { // transform the x,y location from the user-defined // coordinate frame to the screen pixel location PointF pix = _location.Transform( pane ); // Draw the text on the screen, including any frame and background // fill elements if ( pix.X > -100000 && pix.X < 100000 && pix.Y > -100000 && pix.Y < 100000 ) { //if ( this.layoutSize.IsEmpty ) // this.FontSpec.Draw( g, pane.IsPenWidthScaled, this.text, pix.X, pix.Y, // this.location.AlignH, this.location.AlignV, scaleFactor ); //else FontSpec.Draw( g, pane, _text, pix.X, pix.Y, _location.AlignH, _location.AlignV, scaleFactor, _layoutArea ); } }
/// <summary> /// Determine if the specified screen point lies inside the bounding box of this /// <see c_ref="TextObj"/>. This method takes into account rotation and alignment /// parameters of the text, as specified in the <see c_ref="FontSpec"/>. /// </summary> /// <param name="pt">The screen point, in pixels</param> /// <param name="pane"> /// A reference to the <see c_ref="PaneBase"/> object that is the parent or /// owner of this object. /// </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 c_ref="GraphPane"/> object using the /// <see c_ref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <returns>true if the point lies in the bounding box, false otherwise</returns> override public bool PointInBox( PointF pt, PaneBase pane, Graphics g, float scaleFactor ) { if ( ! base.PointInBox(pt, pane, g, scaleFactor ) ) return false; // transform the x,y location from the user-defined // coordinate frame to the screen pixel location PointF pix = _location.Transform( pane ); return _fontSpec.PointInBox( pt, g, _text, pix.X, pix.Y, _location.AlignH, _location.AlignV, scaleFactor, LayoutArea ); }
/// <summary> /// Create a <see c_ref="Pen" /> object based on the properties of this /// <see c_ref="LineBase" />. /// </summary> /// <param name="pane">The owner <see c_ref="GraphPane" /> of this /// <see c_ref="LineBase" />. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see c_ref="GraphPane"/> object using the /// <see c_ref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <param name="dataValue">The data value to be used for a value-based /// color gradient. This is only applicable if <see c_ref="Fill.Type">GradientFill.Type</see> /// is one of <see c_ref="FillType.GradientByX"/>, /// <see c_ref="FillType.GradientByY"/>, <see c_ref="FillType.GradientByZ"/>, /// or <see c_ref="FillType.GradientByColorValue" />. /// </param> /// <returns>A <see c_ref="Pen" /> object with the properties of this <see c_ref="LineBase" /> /// </returns> public Pen GetPen( PaneBase pane, float scaleFactor, PointPair dataValue ) { Color color = _color; if ( _gradientFill.IsGradientValueType ) color = _gradientFill.GetGradientColor( dataValue ); Pen pen = new Pen( color, pane.ScaledPenWidth( _width, scaleFactor ) ); pen.DashStyle = _style; if ( _style == DashStyle.Custom ) { if ( _dashOff > 1e-10 && _dashOn > 1e-10 ) { pen.DashStyle = DashStyle.Custom; float[] pattern = new float[2]; pattern[0] = _dashOn; pattern[1] = _dashOff; pen.DashPattern = pattern; } else pen.DashStyle = DashStyle.Solid; } return pen; }
/// <summary> /// Create a <see c_ref="Pen" /> object based on the properties of this /// <see c_ref="LineBase" />. /// </summary> /// <param name="pane">The owner <see c_ref="GraphPane" /> of this /// <see c_ref="LineBase" />. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see c_ref="GraphPane"/> object using the /// <see c_ref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <returns>A <see c_ref="Pen" /> object with the properties of this <see c_ref="LineBase" /> /// </returns> public Pen GetPen( PaneBase pane, float scaleFactor ) { return GetPen( pane, scaleFactor, null ); }
/* /// <summary> /// Create a new <see c_ref="Pen"/> object from the properties of this /// <see c_ref="Border"/> object. /// </summary> /// <param name="isPenWidthScaled"> /// Set to true to have the <see c_ref="Border"/> pen width scaled with the /// scaleFactor. /// </param> /// <param name="scaleFactor"> /// The scaling factor for the features of the graph based on the <see c_ref="PaneBase.BaseDimension"/>. This /// scaling factor is calculated by the <see c_ref="PaneBase.CalcScaleFactor"/> method. The scale factor /// represents a linear multiple to be applied to font sizes, symbol sizes, etc. /// </param> /// <returns>A <see c_ref="Pen"/> object with the proper color and pen width.</returns> public Pen MakePen( bool isPenWidthScaled, float scaleFactor ) { float scaledPenWidth = _width; if ( isPenWidthScaled ) scaledPenWidth = (float)(_width * scaleFactor); return new Pen( _color, scaledPenWidth ); } */ /// <summary> /// Draw the specified Border (<see c_ref="RectangleF"/>) using the properties of /// this <see c_ref="Border"/> 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 c_ref="PaneBase"/> object that is the parent or /// owner of this object. /// </param> /// <param name="scaleFactor"> /// The scaling factor for the features of the graph based on the <see c_ref="PaneBase.BaseDimension"/>. This /// scaling factor is calculated by the <see c_ref="PaneBase.CalcScaleFactor"/> method. The scale factor /// represents a linear multiple to be applied to font sizes, symbol sizes, etc. /// </param> /// <param name="rect">A <see c_ref="RectangleF"/> struct to be drawn.</param> public void Draw( Graphics g, PaneBase pane, float scaleFactor, RectangleF rect ) { // Need to use the RectangleF props since rounding it can cause the axisFrame to // not line up properly with the last tic mark if ( _isVisible ) { RectangleF tRect = rect; float scaledInflate = _inflateFactor * scaleFactor; tRect.Inflate( scaledInflate, scaledInflate ); using ( Pen pen = GetPen( pane, scaleFactor) ) g.DrawRectangle( pen, tRect.X, tRect.Y, tRect.Width, tRect.Height ); } }
/// <summary> /// Determine if the specified screen point lies inside the bounding box of this /// <see c_ref="BoxObj"/>. /// </summary> /// <param name="pt">The screen point, in pixels</param> /// <param name="pane"> /// A reference to the <see c_ref="PaneBase"/> object that is the parent or /// owner of this object. /// </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 c_ref="GraphPane"/> object using the /// <see c_ref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <returns>true if the point lies in the bounding box, false otherwise</returns> override public bool PointInBox( PointF pt, PaneBase pane, Graphics g, float scaleFactor ) { if ( ! base.PointInBox(pt, pane, g, scaleFactor ) ) return false; // transform the x,y location from the user-defined // coordinate frame to the screen pixel location RectangleF pixRect = _location.TransformRect( pane ); using ( GraphicsPath path = new GraphicsPath() ) { path.AddEllipse( pixRect ); return path.IsVisible( pt ); } }
/// <summary> /// Determine if the specified screen point lies inside the bounding box of this /// <see c_ref="LineObj"/>. /// </summary> /// <remarks>The bounding box is calculated assuming a distance /// of <see c_ref="GraphPane.Default.NearestTol"/> pixels around the arrow segment. /// </remarks> /// <param name="pt">The screen point, in pixels</param> /// <param name="pane"> /// A reference to the <see c_ref="PaneBase"/> object that is the parent or /// owner of this object. /// </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 c_ref="GraphPane"/> object using the /// <see c_ref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <returns>true if the point lies in the bounding box, false otherwise</returns> override public bool PointInBox( PointF pt, PaneBase pane, Graphics g, float scaleFactor ) { if ( ! base.PointInBox(pt, pane, g, scaleFactor ) ) return false; // transform the x,y location from the user-defined // coordinate frame to the screen pixel location PointF pix = _location.TransformTopLeft( pane ); PointF pix2 = _location.TransformBottomRight( pane ); using ( Pen pen = new Pen( Color.Black, (float)GraphPane.Default.NearestTol * 2.0F ) ) { using ( GraphicsPath path = new GraphicsPath() ) { path.AddLine( pix, pix2 ); return path.IsOutlineVisible( pt, pen ); } } }
/// <summary> /// Render this <see c_ref="GraphObj"/> object to the specified <see c_ref="Graphics"/> device. /// </summary> /// <remarks> /// This method is normally only called by the Draw method /// of the parent <see c_ref="GraphObjList"/> collection object. /// </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 c_ref="PaneBase"/> 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 c_ref="PaneBase"/> object using the /// <see c_ref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> abstract public void Draw( Graphics g, PaneBase pane, float scaleFactor );
/// <summary> /// Determines the shape type and Coords values for this GraphObj /// </summary> override public void GetCoords( PaneBase pane, Graphics g, float scaleFactor, out string shape, out string coords ) { // transform the x,y location from the user-defined // coordinate frame to the screen pixel location RectangleF pixRect = _location.TransformRect( pane ); Matrix matrix = new Matrix(); if ( pixRect.Right == 0 ) pixRect.Width = 1; float angle = (float) Math.Atan( ( pixRect.Top - pixRect.Bottom ) / ( pixRect.Left - pixRect.Right ) ); matrix.Rotate( angle, MatrixOrder.Prepend ); // Move the coordinate system to local coordinates // of this text object (that is, at the specified // x,y location) matrix.Translate( -pixRect.Left, -pixRect.Top, MatrixOrder.Prepend ); PointF[] pts = new PointF[4]; pts[0] = new PointF( 0, 3 ); pts[1] = new PointF( pixRect.Width, 3 ); pts[2] = new PointF( pixRect.Width, -3 ); pts[3] = new PointF( 0, -3 ); matrix.TransformPoints( pts ); shape = "poly"; coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0},{4:f0},{5:f0},{6:f0},{7:f0},", pts[0].X, pts[0].Y, pts[1].X, pts[1].Y, pts[2].X, pts[2].Y, pts[3].X, pts[3].Y ); }
/// <summary> /// Determines the shape type and Coords values for this GraphObj /// </summary> abstract public void GetCoords( PaneBase pane, Graphics g, float scaleFactor, out string shape, out string coords );
/// <summary> /// Render the <see c_ref="Legend"/> to the specified <see c_ref="Graphics"/> device. /// </summary> /// <remarks> /// This method is normally only called by the Draw method /// of the parent <see c_ref="GraphPane"/> object. /// </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 c_ref="PaneBase"/> 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 c_ref="GraphPane"/> object using the /// <see c_ref="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, PaneBase pane, float scaleFactor ) { // if the legend is not visible, do nothing if ( !_isVisible ) return; // Fill the background with the specified color if required _fill.Draw( g, _rect ); PaneList paneList = GetPaneList( pane ); float halfGap = _tmpSize / 2.0F; // Check for bad data values if ( _hStack <= 0 ) _hStack = 1; if ( _legendItemWidth <= 0 ) _legendItemWidth = 100; if ( _legendItemHeight <= 0 ) _legendItemHeight = _tmpSize; //float gap = pane.ScaledGap( scaleFactor ); int iEntry = 0; float x, y; // Get a brush for the legend label text using ( SolidBrush brushB = new SolidBrush( Color.Black ) ) { foreach ( GraphPane tmpPane in paneList ) { // Loop for each curve in the CurveList collection //foreach ( CurveItem curve in tmpPane.CurveList ) int count = tmpPane.CurveList.Count; for ( int i = 0; i < count; i++ ) { CurveItem curve = tmpPane.CurveList[_isReverse ? count - i - 1 : i]; if ( curve._label._text != "" && curve._label._isVisible ) { // Calculate the x,y (TopLeft) location of the current // curve legend label // assuming: // charHeight/2 for the left margin, plus legendWidth for each // horizontal column // legendHeight is the line spacing, with no extra margin above x = _rect.Left + halfGap / 2.0F + ( iEntry % _hStack ) * _legendItemWidth; y = _rect.Top + iEntry / _hStack * _legendItemHeight; // Draw the legend label for the current curve FontSpec tmpFont = ( curve._label._fontSpec != null ) ? curve._label._fontSpec : FontSpec; // This is required because, for long labels, the centering can affect the // position in GDI+. tmpFont.StringAlignment = StringAlignment.Near; if ( _isShowLegendSymbols ) { tmpFont.Draw( g, pane, curve._label._text, x + 2.5F * _tmpSize, y + _legendItemHeight / 2.0F+1, AlignH.Left, AlignV.Center, scaleFactor ); RectangleF rect = new RectangleF( x, y + _legendItemHeight / 4.0F, 2 * _tmpSize, _legendItemHeight / 2.0F ); curve.DrawLegendKey( g, tmpPane, rect, scaleFactor ); } else { if ( curve._label._fontSpec == null ) tmpFont.FontColor = curve.Color; tmpFont.Draw(g, pane, curve._label._text, x + 0.0F * _tmpSize, y + _legendItemHeight / 2.0F, AlignH.Left, AlignV.Center, scaleFactor); } // maintain a curve count for positioning iEntry++; } } if ( pane is MasterPane && ( (MasterPane)pane ).IsUniformLegendEntries ) break; } // Draw a border around the legend if required if ( iEntry > 0 ) Border.Draw( g, pane, scaleFactor, _rect ); } }
/// <summary> /// Transform this <see c_ref="Location"/> object to display device /// coordinates using the properties of the specified <see c_ref="GraphPane"/>. /// </summary> /// <param name="pane"> /// A reference to the <see c_ref="PaneBase"/> object that contains /// the <see c_ref="Axis"/> classes which will be used for the transform. /// </param> /// <returns>A point in display device coordinates that corresponds to the /// specified user point.</returns> public PointF Transform( PaneBase pane ) { return Transform( pane, _x, _y, _coordinateFrame ); }
/// <summary> /// Determine if a mouse point is within the legend, and if so, which legend /// entry (<see c_ref="CurveItem"/>) is nearest. /// </summary> /// <param name="mousePt">The screen point, in pixel coordinates.</param> /// <param name="pane"> /// A reference to the <see c_ref="PaneBase"/> 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 c_ref="GraphPane"/> object using the /// <see c_ref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <param name="index">The index number of the <see c_ref="CurveItem"/> legend /// entry that is under the mouse point. The <see c_ref="CurveItem"/> object is /// accessible via <see c_ref="GraphPane.CurveList">CurveList[index]</see>. /// </param> /// <returns>true if the mouse point is within the <see c_ref="Legend"/> bounding /// box, false otherwise.</returns> /// <seealso c_ref="GraphPane.FindNearestObject"/> public bool FindPoint( PointF mousePt, PaneBase pane, float scaleFactor, out int index ) { index = -1; if ( _rect.Contains( mousePt ) ) { int j = (int)( ( mousePt.Y - _rect.Top ) / _legendItemHeight ); int i = (int)( ( mousePt.X - _rect.Left - _tmpSize / 2.0f ) / _legendItemWidth ); if ( i < 0 ) i = 0; if ( i >= _hStack ) i = _hStack - 1; int pos = i + j * _hStack; index = 0; PaneList paneList = GetPaneList( pane ); foreach ( GraphPane tmpPane in paneList ) { foreach ( CurveItem curve in tmpPane.CurveList ) { if ( curve._label._isVisible && curve._label._text != string.Empty ) { if ( pos == 0 ) return true; pos--; } index++; } } return true; } return false; }
/// <summary> /// Transform this <see c_ref="Location"/> from the coordinate system /// as specified by <see c_ref="CoordinateFrame"/> to the device coordinates /// of the specified <see c_ref="PaneBase"/> object. /// </summary> /// <remarks> /// The returned /// <see c_ref="PointF"/> struct represents the top-left corner of the /// object that honors the <see c_ref="Location"/> properties. /// The <see c_ref="AlignH"/> and <see c_ref="AlignV"/> properties are honored in /// this transformation. /// </remarks> /// <param name="pane"> /// A reference to the <see c_ref="PaneBase"/> object that contains /// the <see c_ref="Axis"/> classes which will be used for the transform. /// </param> /// <param name="width">The width of the object in device pixels</param> /// <param name="height">The height of the object in device pixels</param> /// <returns>The top-left corner of the object</returns> public PointF TransformTopLeft( PaneBase pane, float width, float height ) { PointF pt = Transform( pane ); if ( _alignH == AlignH.Right ) pt.X -= width; else if ( _alignH == AlignH.Center ) pt.X -= width / 2.0F; if ( _alignV == AlignV.Bottom ) pt.Y -= height; else if ( _alignV == AlignV.Center ) pt.Y -= height / 2.0F; return pt; }
private PaneList GetPaneList( PaneBase pane ) { // For a single GraphPane, create a PaneList to contain it // Otherwise, just use the paneList from the MasterPane PaneList paneList; if ( pane is GraphPane ) { paneList = new PaneList(); paneList.Add( (GraphPane)pane ); } else paneList = ( (MasterPane)pane ).PaneList; return paneList; }
/// <summary> /// The <see c_ref="PointF"/> for this object as defined by the /// <see c_ref="X2"/> and <see c_ref="Y2"/> properties. /// </summary> /// <remarks> /// This method transforms the location to output device pixel units. /// The <see c_ref="AlignH"/> and <see c_ref="AlignV"/> properties are ignored for /// this transformation (see <see c_ref="TransformTopLeft(PaneBase,float,float)"/>). /// </remarks> /// <value>A <see c_ref="PointF"/> in pixel units.</value> public PointF TransformBottomRight( PaneBase pane ) { return Transform( pane, X2, Y2, _coordinateFrame ); }
/// <summary> /// Calculate the <see c_ref="Legend"/> rectangle (<see c_ref="Rect"/>), /// taking into account the number of required legend /// entries, and the legend drawing preferences. /// </summary> /// <remarks>Adjust the size of the /// <see c_ref="Chart.Rect"/> for the parent <see c_ref="GraphPane"/> to accomodate the /// space required by the legend. /// </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 c_ref="PaneBase"/> 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 c_ref="GraphPane"/> object using the /// <see c_ref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <param name="tChartRect"> /// The rectangle that contains the area bounded by the axes, in pixel units. /// <seealso c_ref="Chart.Rect" /> /// </param> public void CalcRect( Graphics g, PaneBase pane, float scaleFactor, ref RectangleF tChartRect ) { // Start with an empty rectangle _rect = Rectangle.Empty; _hStack = 1; _legendItemWidth = 1; _legendItemHeight = 0; RectangleF clientRect = pane.CalcClientRect( g, scaleFactor ); // If the legend is invisible, don't do anything if ( !_isVisible ) return; int nCurve = 0; PaneList paneList = GetPaneList( pane ); _tmpSize = GetMaxHeight( paneList, g, scaleFactor ); float halfGap = _tmpSize / 2.0F, maxWidth = 0, tmpWidth, gapPix = _gap * _tmpSize; foreach ( GraphPane tmpPane in paneList ) { // Loop through each curve in the curve list // Find the maximum width of the legend labels //foreach ( CurveItem curve in tmpPane.CurveList ) //foreach ( CurveItem curve in GetIterator( tmpPane.CurveList, _isReverse ) ) int count = tmpPane.CurveList.Count; for ( int i = 0; i < count; i++ ) { CurveItem curve = tmpPane.CurveList[_isReverse ? count - i - 1 : i]; if ( curve._label._text != string.Empty && curve._label._isVisible ) { // Calculate the width of the label save the max width FontSpec tmpFont = ( curve._label._fontSpec != null ) ? curve._label._fontSpec : FontSpec; tmpWidth = tmpFont.GetWidth( g, curve._label._text, scaleFactor ); if ( tmpWidth > maxWidth ) maxWidth = tmpWidth; // Save the maximum symbol height for line-type curves if ( curve is LineItem && ( (LineItem)curve ).Symbol.Size > _legendItemHeight ) _legendItemHeight = ( (LineItem)curve ).Symbol.Size; nCurve++; } } if ( pane is MasterPane && ( (MasterPane)pane ).IsUniformLegendEntries ) break; } float widthAvail; // Is this legend horizontally stacked? if ( _isHStack ) { // Determine the available space for horizontal stacking switch ( _position ) { // Never stack if the legend is to the right or left case LegendPos.Right: case LegendPos.Left: widthAvail = 0; break; // for the top & bottom, the axis border width is available case LegendPos.Top: case LegendPos.TopCenter: case LegendPos.Bottom: case LegendPos.BottomCenter: widthAvail = tChartRect.Width; break; // for the top & bottom flush left, the panerect less margins is available case LegendPos.TopFlushLeft: case LegendPos.BottomFlushLeft: widthAvail = clientRect.Width; break; // for inside the axis area or Float, use 1/2 of the axis border width case LegendPos.InsideTopRight: case LegendPos.InsideTopLeft: case LegendPos.InsideBotRight: case LegendPos.InsideBotLeft: case LegendPos.Float: widthAvail = tChartRect.Width / 2; break; // shouldn't ever happen default: widthAvail = 0; break; } // width of one legend entry if ( _isShowLegendSymbols ) _legendItemWidth = 3.0f * _tmpSize + maxWidth; else _legendItemWidth = 0.5f * _tmpSize + maxWidth; // Calculate the number of columns in the legend // Normally, the legend is: // available width / ( max width of any entry + space for line&symbol ) if ( maxWidth > 0 ) _hStack = (int)( ( widthAvail - halfGap ) / _legendItemWidth ); // You can never have more columns than legend entries if ( _hStack > nCurve ) _hStack = nCurve; // a saftey check if ( _hStack == 0 ) _hStack = 1; } else { if ( _isShowLegendSymbols ) _legendItemWidth = 3.0F * _tmpSize + maxWidth; else _legendItemWidth = 0.5F * _tmpSize + maxWidth; } // legend is: // item: space line space text space // width: wid 4*wid wid maxWid wid // The symbol is centered on the line // // legend begins 3 * wid to the right of the plot rect // // The height of the legend is the actual height of the lines of text // (nCurve * hite) plus wid on top and wid on the bottom // total legend width float totLegWidth = _hStack * _legendItemWidth; // The total legend height _legendItemHeight = _legendItemHeight * scaleFactor + halfGap; if ( _tmpSize > _legendItemHeight ) _legendItemHeight = _tmpSize; float totLegHeight = (float)Math.Ceiling( nCurve / (double)_hStack ) * _legendItemHeight; RectangleF newRect = new RectangleF(); // Now calculate the legend rect based on the above determined parameters // Also, adjust the ChartRect to reflect the space for the legend if ( nCurve > 0 ) { newRect = new RectangleF( 0, 0, totLegWidth, totLegHeight ); // The switch statement assigns the left and top edges, and adjusts the ChartRect // as required. The right and bottom edges are calculated at the bottom of the switch. switch ( _position ) { case LegendPos.Right: newRect.X = clientRect.Right - totLegWidth; newRect.Y = tChartRect.Top; tChartRect.Width -= totLegWidth + gapPix; break; case LegendPos.Top: newRect.X = tChartRect.Left; newRect.Y = clientRect.Top; tChartRect.Y += totLegHeight + gapPix; tChartRect.Height -= totLegHeight + gapPix; break; case LegendPos.TopFlushLeft: newRect.X = clientRect.Left; newRect.Y = clientRect.Top; tChartRect.Y += totLegHeight + gapPix * 1.5f; tChartRect.Height -= totLegHeight + gapPix * 1.5f; break; case LegendPos.TopCenter: newRect.X = tChartRect.Left + ( tChartRect.Width - totLegWidth ) / 2; newRect.Y = tChartRect.Top; tChartRect.Y += totLegHeight + gapPix; tChartRect.Height -= totLegHeight + gapPix; break; case LegendPos.Bottom: newRect.X = tChartRect.Left; newRect.Y = clientRect.Bottom - totLegHeight; tChartRect.Height -= totLegHeight + gapPix; break; case LegendPos.BottomFlushLeft: newRect.X = clientRect.Left; newRect.Y = clientRect.Bottom - totLegHeight; tChartRect.Height -= totLegHeight + gapPix; break; case LegendPos.BottomCenter: newRect.X = tChartRect.Left + ( tChartRect.Width - totLegWidth ) / 2; newRect.Y = clientRect.Bottom - totLegHeight; tChartRect.Height -= totLegHeight + gapPix; break; case LegendPos.Left: newRect.X = clientRect.Left; newRect.Y = tChartRect.Top; tChartRect.X += totLegWidth + halfGap; tChartRect.Width -= totLegWidth + gapPix; break; case LegendPos.InsideTopRight: newRect.X = tChartRect.Right - totLegWidth; newRect.Y = tChartRect.Top; break; case LegendPos.InsideTopLeft: newRect.X = tChartRect.Left; newRect.Y = tChartRect.Top; break; case LegendPos.InsideBotRight: newRect.X = tChartRect.Right - totLegWidth; newRect.Y = tChartRect.Bottom - totLegHeight; break; case LegendPos.InsideBotLeft: newRect.X = tChartRect.Left; newRect.Y = tChartRect.Bottom - totLegHeight; break; case LegendPos.Float: newRect.Location = Location.TransformTopLeft( pane, totLegWidth, totLegHeight ); break; } } _rect = newRect; }
/// <summary> /// The Copy Constructor /// </summary> /// <param name="rhs">The <see c_ref="PaneBase"/> object from which to copy</param> public PaneBase( PaneBase rhs ) { // copy over all the value types _isFontsScaled = rhs._isFontsScaled; _isPenWidthScaled = rhs._isPenWidthScaled; _titleGap = rhs._titleGap; _baseDimension = rhs._baseDimension; _margin = rhs._margin.Clone(); _rect = rhs._rect; // Copy the reference types by cloning _fill = rhs._fill.Clone(); _border = rhs._border.Clone(); _title = rhs._title.Clone(); _legend = rhs.Legend.Clone(); _title = rhs._title.Clone(); _graphObjList = rhs._graphObjList.Clone(); if ( rhs._tag is ICloneable ) _tag = ((ICloneable) rhs._tag).Clone(); else _tag = rhs._tag; }
/// <summary> /// Render this object to the specified <see c_ref="Graphics"/> device. /// </summary> /// <remarks> /// This method is normally only called by the Draw method /// of the parent <see c_ref="GraphObjList"/> collection object. /// </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 c_ref="PaneBase"/> 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 c_ref="GraphPane"/> object using the /// <see c_ref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> override public void Draw( Graphics g, PaneBase pane, float scaleFactor ) { // Convert the arrow coordinates from the user coordinate system // to the screen coordinate system RectangleF pixRect = Location.TransformRect( pane ); if ( Math.Abs( pixRect.Left ) < 100000 && Math.Abs( pixRect.Top ) < 100000 && Math.Abs( pixRect.Right ) < 100000 && Math.Abs( pixRect.Bottom ) < 100000 ) { if ( _fill.IsVisible ) using ( Brush brush = _fill.MakeBrush( pixRect ) ) g.FillEllipse( brush, pixRect ); if ( _border.IsVisible ) using ( Pen pen = _border.GetPen( pane, scaleFactor ) ) g.DrawEllipse( pen, pixRect ); } }
/// <summary> /// Render the specified <paramref name="text"/> to the specifed /// <see c_ref="Graphics"/> device. The text, border, and fill options /// will be rendered as required. /// </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 c_ref="PaneBase"/> object that is the parent or /// owner of this object. /// </param> /// <param name="text">A string value containing the text to be /// displayed. This can be multiple lines, separated by newline ('\n') /// characters</param> /// <param name="x">The X location to display the text, in screen /// coordinates, relative to the horizontal (<see c_ref="AlignH"/>) /// alignment parameter <paramref name="alignH"/></param> /// <param name="y">The Y location to display the text, in screen /// coordinates, relative to the vertical (<see c_ref="AlignV"/> /// alignment parameter <paramref name="alignV"/></param> /// <param name="alignH">A horizontal alignment parameter specified /// using the <see c_ref="AlignH"/> enum type</param> /// <param name="alignV">A vertical alignment parameter specified /// using the <see c_ref="AlignV"/> enum type</param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see c_ref="GraphPane"/> object using the /// <see c_ref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <param name="layoutArea">The limiting area (<see c_ref="SizeF"/>) into which the text /// must fit. The actual rectangle may be smaller than this, but the text will be wrapped /// to accomodate the area.</param> public void Draw( Graphics g, PaneBase pane, string text, float x, float y, AlignH alignH, AlignV alignV, float scaleFactor, SizeF layoutArea ) { // make sure the font size is properly scaled //Remake( scaleFactor, this.Size, ref this.scaledSize, ref this.font ); SmoothingMode sModeSave = g.SmoothingMode; TextRenderingHint sHintSave = g.TextRenderingHint; if ( _isAntiAlias ) { g.SmoothingMode = SmoothingMode.HighQuality; g.TextRenderingHint = TextRenderingHint.AntiAlias; } SizeF sizeF; if ( layoutArea.IsEmpty ) sizeF = MeasureString( g, text, scaleFactor ); else sizeF = MeasureString( g, text, scaleFactor, layoutArea ); // Save the old transform matrix for later restoration Matrix saveMatrix = g.Transform; g.Transform = SetupMatrix( g.Transform, x, y, sizeF, alignH, alignV, _angle ); // Create a rectangle representing the border around the // text. Note that, while the text is drawn based on the // TopCenter position, the rectangle is drawn based on // the TopLeft position. Therefore, move the rectangle // width/2 to the left to align it properly RectangleF rectF = new RectangleF( -sizeF.Width / 2.0F, 0.0F, sizeF.Width, sizeF.Height ); // If the background is to be filled, fill it _fill.Draw( g, rectF ); // Draw the border around the text if required _border.Draw( g, pane, scaleFactor, rectF ); // make a center justified StringFormat alignment // for drawing the text StringFormat strFormat = new StringFormat(); strFormat.Alignment = _stringAlignment; // if ( this.stringAlignment == StringAlignment.Far ) // g.TranslateTransform( sizeF.Width / 2.0F, 0F, MatrixOrder.Prepend ); // else if ( this.stringAlignment == StringAlignment.Near ) // g.TranslateTransform( -sizeF.Width / 2.0F, 0F, MatrixOrder.Prepend ); // Draw the drop shadow text. Note that the coordinate system // is set up such that 0,0 is at the location where the // CenterTop of the text needs to be. if ( _isDropShadow ) { float xShift = (float)( Math.Cos( _dropShadowAngle ) * _dropShadowOffset * _font.Height ); float yShift = (float)( Math.Sin( _dropShadowAngle ) * _dropShadowOffset * _font.Height ); RectangleF rectD = rectF; rectD.Offset( xShift, yShift ); // make a solid brush for rendering the font itself using ( SolidBrush brushD = new SolidBrush( _dropShadowColor ) ) g.DrawString( text, _font, brushD, rectD, strFormat ); } // make a solid brush for rendering the font itself using ( SolidBrush brush = new SolidBrush( _fontColor ) ) { // Draw the actual text. Note that the coordinate system // is set up such that 0,0 is at the location where the // CenterTop of the text needs to be. //RectangleF layoutArea = new RectangleF( 0.0F, 0.0F, sizeF.Width, sizeF.Height ); g.DrawString( text, _font, brush, rectF, strFormat ); } // Restore the transform matrix back to original g.Transform = saveMatrix; g.SmoothingMode = sModeSave; g.TextRenderingHint = sHintSave; }
/// <summary> /// Determine if the specified screen point lies inside the bounding box of this /// <see c_ref="BoxObj"/>. /// </summary> /// <param name="pt">The screen point, in pixels</param> /// <param name="pane"> /// A reference to the <see c_ref="PaneBase"/> object that is the parent or /// owner of this object. /// </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 c_ref="GraphPane"/> object using the /// <see c_ref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <returns>true if the point lies in the bounding box, false otherwise</returns> override public bool PointInBox( PointF pt, PaneBase pane, Graphics g, float scaleFactor ) { if ( ! base.PointInBox(pt, pane, g, scaleFactor ) ) return false; // transform the x,y location from the user-defined // coordinate frame to the screen pixel location RectangleF pixRect = _location.TransformRect( pane ); return pixRect.Contains( pt ); }