示例#1
0
        /// <summary>
        /// Calculate the <see cref="Legend"/> rectangle (see cref="Rect"/>),
        /// taking into account the number of required legend
        /// entries, and the legend drawing preferences.  Adjust the size of the
        /// <see cref="GraphPane.AxisRect"/> for the parent <see cref="GraphPane"/> to accomodate the
        /// space required by the legend.
        /// </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="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="GraphPane.CalcScaleFactor"/> method, and is used to proportionally adjust
        /// font sizes, etc. according to the actual size of the graph.
        /// </param>
        /// <param name="axisRect">
        /// The rectangle that contains the area bounded by the axes, in pixel units.
        /// <seealso cref="ZedGraph.AxisRect">AxisRect</seealso>
        /// </param>
        /// <param name="hStack">The number of columns (horizontal stacking) to be used
        /// for drawing the legend</param>
        /// <param name="legendWidth">The width of each column in the legend (pixels)</param>
        public void CalcRect(Graphics g, GraphPane pane, double scaleFactor,
                             ref RectangleF axisRect, out int hStack,
                             out float legendWidth)
        {
            // Start with an empty rectangle
            this.rect   = Rectangle.Empty;
            hStack      = 1;
            legendWidth = 1;

            // If the legend is invisible, don't do anything
            if (!this.isVisible)
            {
                return;
            }

            int   nCurve         = 0;
            float charHeight     = this.FontSpec.GetHeight(scaleFactor),
                  halfCharHeight = charHeight / 2.0F,
                  charWidth      = this.FontSpec.GetWidth(g, scaleFactor),
                  gap            = pane.ScaledGap(scaleFactor),
                  maxWidth       = 0,
                  tmpWidth;

            // Loop through each curve in the curve list
            // Find the maximum width of the legend labels
            foreach (CurveItem curve in pane.CurveList)
            {
                // Calculate the width of the label save the max width

                tmpWidth = this.FontSpec.GetWidth(g, curve.Label, scaleFactor);

                if (tmpWidth > maxWidth)
                {
                    maxWidth = tmpWidth;
                }

                nCurve++;
            }

            float widthAvail;

            // Is this legend horizontally stacked?
            if (this.isHStack)
            {
                // Determine the available space for horizontal stacking
                switch (this.location)
                {
                // Never stack if the legend is to the right or left
                case LegendLoc.Right:
                case LegendLoc.Left:
                    widthAvail = 0;
                    break;

                // for the top & bottom, the axis frame width is available
                case LegendLoc.Top:
                case LegendLoc.Bottom:
                    widthAvail = pane.AxisRect.Width;
                    break;

                // for inside the axis area, use 1/2 of the axis frame width
                case LegendLoc.InsideTopRight:
                case LegendLoc.InsideTopLeft:
                case LegendLoc.InsideBotRight:
                case LegendLoc.InsideBotLeft:
                    widthAvail = pane.AxisRect.Width / 2;
                    break;

                // shouldn't ever happen
                default:
                    widthAvail = 0;
                    break;
                }

                // width of one legend entry
                legendWidth = 3 * charHeight + 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 - halfCharHeight) / legendWidth);
                }

                // You can never have more columns than legend entries
                if (hStack > nCurve)
                {
                    hStack = nCurve;
                }

                // a saftey check
                if (hStack == 0)
                {
                    hStack = 1;
                }
            }
            else
            {
                legendWidth = 3.5F * charHeight + 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 * legendWidth;

            // The total legend height
            float legHeight = (float)Math.Ceiling((double)nCurve / (double)hStack)
                              * charHeight;

            // Now calculate the legend rect based on the above determined parameters
            // Also, adjust the plotArea and axisRect to reflect the space for the legend
            if (nCurve > 0)
            {
                // The switch statement assigns the left and top edges, and adjusts the axisRect
                // as required.  The right and bottom edges are calculated at the bottom of the switch.
                switch (this.location)
                {
                case LegendLoc.Right:
                    this.rect.X = pane.PaneRect.Right - totLegWidth - gap;
                    this.rect.Y = axisRect.Top;

                    axisRect.Width -= totLegWidth + halfCharHeight;
                    break;

                case LegendLoc.Top:
                    this.rect.X = axisRect.Left;
                    this.rect.Y = axisRect.Top;

                    axisRect.Y      += legHeight + halfCharHeight;
                    axisRect.Height -= legHeight + halfCharHeight;
                    break;

                case LegendLoc.Bottom:
                    this.rect.X = axisRect.Left;
                    this.rect.Y = pane.PaneRect.Bottom - legHeight - gap;

                    axisRect.Height -= legHeight + halfCharHeight;
                    break;

                case LegendLoc.Left:
                    this.rect.X = pane.PaneRect.Left + gap;
                    this.rect.Y = axisRect.Top;

                    axisRect.X     += totLegWidth + halfCharHeight;
                    axisRect.Width -= totLegWidth + halfCharHeight;
                    break;

                case LegendLoc.InsideTopRight:
                    this.rect.X = axisRect.Right - totLegWidth;
                    this.rect.Y = axisRect.Top;
                    break;

                case LegendLoc.InsideTopLeft:
                    this.rect.X = axisRect.Left;
                    this.rect.Y = axisRect.Top;
                    break;

                case LegendLoc.InsideBotRight:
                    this.rect.X = axisRect.Right - totLegWidth;
                    this.rect.Y = axisRect.Bottom - legHeight;
                    break;

                case LegendLoc.InsideBotLeft:
                    this.rect.X = axisRect.Left;
                    this.rect.Y = axisRect.Bottom - legHeight;
                    break;
                }

                // Calculate the Right and Bottom edges of the rect
                this.rect.Width  = totLegWidth;
                this.rect.Height = legHeight;
            }
        }
示例#2
0
文件: Legend.cs 项目: InsungChoi/dddd
        /// <summary>
        /// Calculate the <see cref="Legend"/> rectangle (<see cref="Rect"/>),
        /// taking into account the number of required legend
        /// entries, and the legend drawing preferences.
        /// </summary>
        /// <remarks>Adjust the size of the
        /// <see cref="GraphPane.AxisRect"/> for the parent <see cref="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 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="GraphPane.CalcScaleFactor"/> method, and is used to proportionally adjust
        /// font sizes, etc. according to the actual size of the graph.
        /// </param>
        /// <param name="tAxisRect">
        /// The rectangle that contains the area bounded by the axes, in pixel units.
        /// <seealso cref="GraphPane.AxisRect">AxisRect</seealso>
        /// </param>
        /// <param name="hStack">The number of columns (horizontal stacking) to be used
        /// for drawing the legend</param>
        /// <param name="legendWidth">The width of each column in the legend (pixels)</param>
        /// <param name="legendHeight">The height of each row in the legend (pixels)</param>
        public void CalcRect(Graphics g, GraphPane pane, double scaleFactor,
                                        ref RectangleF tAxisRect, out int hStack,
								        out float legendWidth, out float legendHeight )
        {
            // Start with an empty rectangle
            this.rect = Rectangle.Empty;
            hStack = 1;
            legendWidth = 1;
            legendHeight = 0;

            // If the legend is invisible, don't do anything
            if ( !this.isVisible )
                return;

            int		nCurve = 0;
            float	charHeight = this.FontSpec.GetHeight( scaleFactor ),
                    halfCharHeight = charHeight / 2.0F,
                    charWidth = this.FontSpec.GetWidth( g, scaleFactor ),
                    gap = pane.ScaledGap( scaleFactor ),
                    maxWidth = 0,
                    tmpWidth;

            // Loop through each curve in the curve list
            // Find the maximum width of the legend labels
            foreach( CurveItem curve in pane.CurveList )
            {
                if ( curve.IsLegendLabelVisible && curve.Label != "" )
                {
                    // Calculate the width of the label save the max width

                    tmpWidth = this.FontSpec.GetWidth( g, curve.Label, scaleFactor );

                    if ( tmpWidth > maxWidth )
                        maxWidth = tmpWidth;

                    // Save the maximum symbol height for line-type curves
                    if (curve is LineItem && ((LineItem)curve).Symbol.Size > legendHeight)
                        legendHeight = ((LineItem)curve).Symbol.Size;

                    nCurve++;
                }
            }

            float widthAvail;

            // Is this legend horizontally stacked?
            if ( this.isHStack )
            {
                // Determine the available space for horizontal stacking
                switch( this.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.Bottom:
                        widthAvail = tAxisRect.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 = tAxisRect.Width / 2;
                        break;

                    // shouldn't ever happen
                    default:
                        widthAvail = 0;
                        break;
                }

                // width of one legend entry
                legendWidth = 3 * charHeight + 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 - halfCharHeight) / legendWidth );

                // You can never have more columns than legend entries
                if ( hStack > nCurve )
                    hStack = nCurve;

                // a saftey check
                if ( hStack == 0 )
                    hStack = 1;
            }
            else
                legendWidth = 3.5F * charHeight + 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 * legendWidth;

            // The total legend height
            legendHeight = legendHeight * (float) scaleFactor + halfCharHeight;
            if (charHeight > legendHeight)
                legendHeight = charHeight;
            float totLegHeight = (float) Math.Ceiling( (double) nCurve / (double) hStack )
                                    * legendHeight;

            RectangleF newRect = new RectangleF();

            // Now calculate the legend rect based on the above determined parameters
            // Also, adjust the axisRect 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 axisRect
                // as required.  The right and bottom edges are calculated at the bottom of the switch.
                switch( this.position )
                {
                    case LegendPos.Right:
                        newRect.X = pane.PaneRect.Right - totLegWidth - gap;
                        newRect.Y = tAxisRect.Top;

                        tAxisRect.Width -= totLegWidth + halfCharHeight;
                        break;
                    case LegendPos.Top:
                        newRect.X = tAxisRect.Left;
                        newRect.Y = tAxisRect.Top;

                        tAxisRect.Y += totLegHeight + halfCharHeight;
                        tAxisRect.Height -= totLegHeight + halfCharHeight;
                        break;
                    case LegendPos.Bottom:
                        newRect.X = tAxisRect.Left;
                        newRect.Y = pane.PaneRect.Bottom - totLegHeight - gap;

                        tAxisRect.Height -= totLegHeight + halfCharHeight;
                        break;
                    case LegendPos.Left:
                        newRect.X = pane.PaneRect.Left + gap;
                        newRect.Y = tAxisRect.Top;

                        tAxisRect.X += totLegWidth + halfCharHeight;
                        tAxisRect.Width -= totLegWidth + halfCharHeight;
                        break;
                    case LegendPos.InsideTopRight:
                        newRect.X = tAxisRect.Right - totLegWidth;
                        newRect.Y = tAxisRect.Top;
                        break;
                    case LegendPos.InsideTopLeft:
                        newRect.X = tAxisRect.Left;
                        newRect.Y = tAxisRect.Top;
                        break;
                    case LegendPos.InsideBotRight:
                        newRect.X = tAxisRect.Right - totLegWidth;
                        newRect.Y = tAxisRect.Bottom - totLegHeight;
                        break;
                    case LegendPos.InsideBotLeft:
                        newRect.X = tAxisRect.Left;
                        newRect.Y = tAxisRect.Bottom - totLegHeight;
                        break;
                    case LegendPos.Float:
                        newRect.Location = this.Location.TransformTopLeft( pane, totLegWidth, totLegHeight );
                        break;
                }
            }

            this.rect = newRect;
        }
示例#3
0
        /// <summary>
        /// Render the <see cref="Legend"/> to the specified <see cref="Graphics"/> device
        /// This method is normally only called by the Draw method
        /// of the parent <see cref="GraphPane"/> 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="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="GraphPane.CalcScaleFactor"/> method, and is used to proportionally adjust
        /// font sizes, etc. according to the actual size of the graph.
        /// </param>
        /// <param name="hStack">The number of columns (horizontal stacking) to be used
        /// for drawing the legend</param>
        /// <param name="legendWidth">The width of each column in the legend</param>
        public void Draw(Graphics g, GraphPane pane, double scaleFactor,
                         int hStack, float legendWidth)
        {
            // if the legend is not visible, do nothing
            if (!this.isVisible)
            {
                return;
            }

            // Fill the background with the specified color if required
            if (this.isFilled)
            {
                SolidBrush brush = new SolidBrush(this.fillColor);
                g.FillRectangle(brush, this.rect);
            }

            // Set up some scaled dimensions for calculating sizes and locations
            float charHeight     = this.FontSpec.GetHeight(scaleFactor),
                  halfCharHeight = charHeight / 2.0F;
            float charWidth      = this.FontSpec.GetWidth(g, scaleFactor);
            float gap            = pane.ScaledGap(scaleFactor);

            int   iEntry = 0;
            float x, y;

            // Get a brush for the legend label text
            SolidBrush brushB = new SolidBrush(Color.Black);

            // Loop for each curve in the CurveList collection
            foreach (CurveItem curve in pane.CurveList)
            {
                // 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
                //  charHeight is the line spacing, with no extra margin above
                x = this.rect.Left + halfCharHeight +
                    (iEntry % hStack) * legendWidth;
                y = this.rect.Top + (int)(iEntry / hStack) * charHeight;
                // Draw the legend label for the current curve
                this.FontSpec.Draw(g, curve.Label, x + 2.5F * charHeight, y,
                                   FontAlignH.Left, FontAlignV.Top, scaleFactor);

                // Draw a sample curve to the left of the label text
                curve.Line.Draw(g, x, y + charHeight / 2,
                                x + 2 * charHeight, y + halfCharHeight);
                // Draw a sample symbol to the left of the label text
                curve.Symbol.Draw(g, x + charHeight, y + halfCharHeight,
                                  scaleFactor);

                // maintain a curve count for positioning
                iEntry++;
            }


            // Draw a frame around the legend if required
            if (iEntry > 0 && this.isFramed)
            {
                Pen pen = new Pen(this.frameColor, this.frameWidth);
                g.DrawRectangle(pen, Rectangle.Round(this.rect));
            }
        }
示例#4
0
文件: Axis.cs 项目: InsungChoi/dddd
        /// <summary>
        /// Calculate the space required for this <see cref="Axis"/>
        /// object.  This is the space between the paneRect and the axisRect for
        /// this particular axis.
        /// </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="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="GraphPane.CalcScaleFactor"/> method, and is used to proportionally adjust
        /// font sizes, etc. according to the actual size of the graph.
        /// </param>
        /// <returns>Returns the space, in pixels, required for this axis (between the
        /// paneRect and axisRect)</returns>
        public float CalcSpace( Graphics g, GraphPane pane, double scaleFactor )
        {
            float charHeight = this.ScaleFontSpec.GetHeight( scaleFactor );
            float gap = pane.ScaledGap( scaleFactor );
            float ticSize = this.ScaledTic( scaleFactor );

            // axisRect is the actual area of the plot as bounded by the axes

            // Always leave 1xgap space, even if no axis is displayed
            float space = gap;

            // Account for the Axis
            if ( this.isVisible )
            {
                // tic takes up 1x tic
                // space between tic and scale label is 0.5 tic
                // scale label is GetScaleMaxSpace()
                // space between scale label and axis label is 0.5 tic
                space += this.GetScaleMaxSpace( g, pane, scaleFactor ).Height +
                            ticSize * 2.0F;

                // Only add space for the label if there is one
                // Axis Title gets actual height plus 1x gap
                if ( this.title.Length > 0 && this.isShowTitle )
                {
                    space += this.TitleFontSpec.BoundingBox( g, this.title, scaleFactor ).Height;
                }
            }

            // for the Y axes, make sure that enough space is left to fit the first
            // and last X axis scale label
            if ( ( ( this is YAxis ) || ( this is Y2Axis ) ) && pane.XAxis.IsVisible )
            {
                float tmpSpace =
                    pane.XAxis.GetScaleMaxSpace( g, pane, scaleFactor ).Width / 2.0F +
                        charHeight;
                if ( tmpSpace > space )
                    space = tmpSpace;
            }

            // Verify that the minSpace property was satisfied
            space = Math.Max( space, this.minSpace * (float) scaleFactor );

            return space;
        }