/*!
  \brief Recalculate the geometry of all components.

  \param plot Plot to be layout
  \param plotRect Rect where to place the components
  \param options Options

  \sa invalidate(), titleRect(),
      legendRect(), scaleRect(), canvasRect()
*/
void QwtPlotLayout::activate(const QwtPlot *plot,
                             const QRect &plotRect, int options)
{
    invalidate();

    QRect rect(plotRect);  // undistributed rest of the plot rect

    if ( !(options & IgnoreMargin) ) {
        // subtract the margin

        rect.setRect(
            rect.x() + d_data->margin,
            rect.y() + d_data->margin,
            rect.width() - 2 * d_data->margin,
            rect.height() - 2 * d_data->margin
        );
    }

    // We extract all layout relevant data from the widgets,
    // filter them through pfilter and save them to d_data->layoutData.

    d_data->layoutData.init(plot, rect);

    if (!(options & IgnoreLegend)
            && d_data->legendPos != QwtPlot::ExternalLegend
            && plot->legend() && !plot->legend()->isEmpty() ) {
        d_data->legendRect = layoutLegend(options, rect);

        // subtract d_data->legendRect from rect

        const QRegion region(rect);
        rect = region.subtract(d_data->legendRect).boundingRect();

        if ( d_data->layoutData.legend.frameWidth &&
                !(options & IgnoreFrames ) ) {
            // In case of a frame we have to insert a spacing.
            // Otherwise the leading of the font separates
            // legend and scale/canvas

            switch(d_data->legendPos) {
            case QwtPlot::LeftLegend:
                rect.setLeft(rect.left() + d_data->spacing);
                break;
            case QwtPlot::RightLegend:
                rect.setRight(rect.right() - d_data->spacing);
                break;
            case QwtPlot::TopLegend:
                rect.setTop(rect.top() + d_data->spacing);
                break;
            case QwtPlot::BottomLegend:
                rect.setBottom(rect.bottom() - d_data->spacing);
                break;
            case QwtPlot::ExternalLegend:
                break; // suppress compiler warning
            }
        }
    }

#ifdef __GNUC__
#endif
    /*
     +---+-----------+---+
     |       Title       |
     +---+-----------+---+
     |   |   Axis    |   |
     +---+-----------+---+
     | A |           | A |
     | x |  Canvas   | x |
     | i |           | i |
     | s |           | s |
     +---+-----------+---+
     |   |   Axis    |   |
     +---+-----------+---+
    */

    // axes and title include text labels. The height of each
    // label depends on its line breaks, that depend on the width
    // for the label. A line break in a horizontal text will reduce
    // the available width for vertical texts and vice versa.
    // expandLineBreaks finds the height/width for title and axes
    // including all line breaks.

    int dimTitle, dimAxes[QwtPlot::axisCnt];
    expandLineBreaks(options, rect, dimTitle, dimAxes);

    if (dimTitle > 0 ) {
        d_data->titleRect = QRect(rect.x(), rect.y(),
                                  rect.width(), dimTitle);

        if ( d_data->layoutData.scale[QwtPlot::yLeft].isEnabled !=
                d_data->layoutData.scale[QwtPlot::yRight].isEnabled ) {
            // if only one of the y axes is missing we align
            // the title centered to the canvas

            d_data->titleRect.setX(rect.x() + dimAxes[QwtPlot::yLeft]);
            d_data->titleRect.setWidth(rect.width()
                                       - dimAxes[QwtPlot::yLeft] - dimAxes[QwtPlot::yRight]);
        }

        // subtract title
        rect.setTop(rect.top() + dimTitle + d_data->spacing);
    }

    d_data->canvasRect.setRect(
        rect.x() + dimAxes[QwtPlot::yLeft],
        rect.y() + dimAxes[QwtPlot::xTop],
        rect.width() - dimAxes[QwtPlot::yRight] - dimAxes[QwtPlot::yLeft],
        rect.height() - dimAxes[QwtPlot::xBottom] - dimAxes[QwtPlot::xTop]);

    for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) {
        // set the rects for the axes

        if ( dimAxes[axis] ) {
            int dim = dimAxes[axis];
            QRect &scaleRect = d_data->scaleRect[axis];

            scaleRect = d_data->canvasRect;
            switch(axis) {
            case QwtPlot::yLeft:
                scaleRect.setX(d_data->canvasRect.left() - dim);
                scaleRect.setWidth(dim);
                break;
            case QwtPlot::yRight:
                scaleRect.setX(d_data->canvasRect.right() + 1);
                scaleRect.setWidth(dim);
                break;
            case QwtPlot::xBottom:
                scaleRect.setY(d_data->canvasRect.bottom() + 1);
                scaleRect.setHeight(dim);
                break;
            case QwtPlot::xTop:
                scaleRect.setY(d_data->canvasRect.top() - dim);
                scaleRect.setHeight(dim);
                break;
            }
#if QT_VERSION < 0x040000
            scaleRect = scaleRect.normalize();
#else
            scaleRect = scaleRect.normalized();
#endif
        }
    }

    // +---+-----------+---+
    // |  <-   Axis   ->   |
    // +-^-+-----------+-^-+
    // | | |           | | |
    // |   |           |   |
    // | A |           | A |
    // | x |  Canvas   | x |
    // | i |           | i |
    // | s |           | s |
    // |   |           |   |
    // | | |           | | |
    // +-V-+-----------+-V-+
    // |   <-  Axis   ->   |
    // +---+-----------+---+

    // The ticks of the axes - not the labels above - should
    // be aligned to the canvas. So we try to use the empty
    // corners to extend the axes, so that the label texts
    // left/right of the min/max ticks are moved into them.

    alignScales(options, d_data->canvasRect, d_data->scaleRect);

    if (!d_data->legendRect.isEmpty() ) {
        // We prefer to align the legend to the canvas - not to
        // the complete plot - if possible.

        d_data->legendRect = alignLegend(d_data->canvasRect, d_data->legendRect);
    }
}
Exemple #2
0
/*!
  \brief Recalculate the geometry of all components.

  \param plot Plot to be layout
  \param plotRect Rectangle where to place the components
  \param options Layout options

  \sa invalidate(), titleRect(), footerRect()
      legendRect(), scaleRect(), canvasRect()
*/
void QwtPlotLayout::activate( const QwtPlot *plot,
    const QRectF &plotRect, Options options )
{
    invalidate();

    QRectF rect( plotRect );  // undistributed rest of the plot rect

    // We extract all layout relevant parameters from the widgets,
    // and save them to d_data->layoutData.

    d_data->layoutData.init( plot, rect );

    if ( !( options & IgnoreLegend )
        && plot->legend() && !plot->legend()->isEmpty() )
    {
        d_data->legendRect = layoutLegend( options, rect );

        // subtract d_data->legendRect from rect

        const QRegion region( rect.toRect() );
        rect = region.subtracted( d_data->legendRect.toRect() ).boundingRect();

        switch ( d_data->legendPos )
        {
            case QwtPlot::LeftLegend:
                rect.setLeft( rect.left() + d_data->spacing );
                break;
            case QwtPlot::RightLegend:
                rect.setRight( rect.right() - d_data->spacing );
                break;
            case QwtPlot::TopLegend:
                rect.setTop( rect.top() + d_data->spacing );
                break;
            case QwtPlot::BottomLegend:
                rect.setBottom( rect.bottom() - d_data->spacing );
                break;
        }
    }

    /*
     +---+-----------+---+
     |       Title       |
     +---+-----------+---+
     |   |   Axis    |   |
     +---+-----------+---+
     | A |           | A |
     | x |  Canvas   | x |
     | i |           | i |
     | s |           | s |
     +---+-----------+---+
     |   |   Axis    |   |
     +---+-----------+---+
     |      Footer       |
     +---+-----------+---+
    */

    // title, footer and axes include text labels. The height of each
    // label depends on its line breaks, that depend on the width
    // for the label. A line break in a horizontal text will reduce
    // the available width for vertical texts and vice versa.
    // expandLineBreaks finds the height/width for title, footer and axes
    // including all line breaks.

    int dimTitle, dimFooter, dimAxes[QwtPlot::axisCnt];
    expandLineBreaks( options, rect, dimTitle, dimFooter, dimAxes );

    if ( dimTitle > 0 )
    {
        d_data->titleRect.setRect(
            rect.left(), rect.top(), rect.width(), dimTitle );

        rect.setTop( d_data->titleRect.bottom() + d_data->spacing );

        if ( d_data->layoutData.scale[QwtPlot::yLeft].isEnabled !=
            d_data->layoutData.scale[QwtPlot::yRight].isEnabled )
        {
            // if only one of the y axes is missing we align
            // the title centered to the canvas

            d_data->titleRect.setX( rect.left() + dimAxes[QwtPlot::yLeft] );
            d_data->titleRect.setWidth( rect.width()
                - dimAxes[QwtPlot::yLeft] - dimAxes[QwtPlot::yRight] );
        }
    }

    if ( dimFooter > 0 )
    {
        d_data->footerRect.setRect(
            rect.left(), rect.bottom() - dimFooter, rect.width(), dimFooter );

        rect.setBottom( d_data->footerRect.top() - d_data->spacing );

        if ( d_data->layoutData.scale[QwtPlot::yLeft].isEnabled !=
            d_data->layoutData.scale[QwtPlot::yRight].isEnabled )
        {
            // if only one of the y axes is missing we align
            // the footer centered to the canvas

            d_data->footerRect.setX( rect.left() + dimAxes[QwtPlot::yLeft] );
            d_data->footerRect.setWidth( rect.width()
                - dimAxes[QwtPlot::yLeft] - dimAxes[QwtPlot::yRight] );
        }
    }

    d_data->canvasRect.setRect(
        rect.x() + dimAxes[QwtPlot::yLeft],
        rect.y() + dimAxes[QwtPlot::xTop],
        rect.width() - dimAxes[QwtPlot::yRight] - dimAxes[QwtPlot::yLeft],
        rect.height() - dimAxes[QwtPlot::xBottom] - dimAxes[QwtPlot::xTop] );

    for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
    {
        // set the rects for the axes

        if ( dimAxes[axis] )
        {
            int dim = dimAxes[axis];
            QRectF &scaleRect = d_data->scaleRect[axis];

            scaleRect = d_data->canvasRect;
            switch ( axis )
            {
                case QwtPlot::yLeft:
                    scaleRect.setX( d_data->canvasRect.left() - dim );
                    scaleRect.setWidth( dim );
                    break;
                case QwtPlot::yRight:
                    scaleRect.setX( d_data->canvasRect.right() );
                    scaleRect.setWidth( dim );
                    break;
                case QwtPlot::xBottom:
                    scaleRect.setY( d_data->canvasRect.bottom() );
                    scaleRect.setHeight( dim );
                    break;
                case QwtPlot::xTop:
                    scaleRect.setY( d_data->canvasRect.top() - dim );
                    scaleRect.setHeight( dim );
                    break;
            }
            scaleRect = scaleRect.normalized();
        }
    }

    // +---+-----------+---+
    // |  <-   Axis   ->   |
    // +-^-+-----------+-^-+
    // | | |           | | |
    // |   |           |   |
    // | A |           | A |
    // | x |  Canvas   | x |
    // | i |           | i |
    // | s |           | s |
    // |   |           |   |
    // | | |           | | |
    // +-V-+-----------+-V-+
    // |   <-  Axis   ->   |
    // +---+-----------+---+

    // The ticks of the axes - not the labels above - should
    // be aligned to the canvas. So we try to use the empty
    // corners to extend the axes, so that the label texts
    // left/right of the min/max ticks are moved into them.

    alignScales( options, d_data->canvasRect, d_data->scaleRect );

    if ( !d_data->legendRect.isEmpty() )
    {
        // We prefer to align the legend to the canvas - not to
        // the complete plot - if possible.

        d_data->legendRect = alignLegend( d_data->canvasRect, d_data->legendRect );
    }
}