Skip to content
qwt_plot_layout.cpp 35.6 KiB
Newer Older
pixhawk's avatar
pixhawk committed
        int fw = 0;
        if ( !(options & IgnoreFrames) )
            fw = d_data->layoutData.canvas.frameWidth;

        if ( scaleRect[QwtPlot::xBottom].isValid() &&
            scaleRect[QwtPlot::xTop].isValid() )
        {
            for ( int axis = QwtPlot::xBottom; axis <= QwtPlot::xTop; axis++ )
            {
                scaleRect[axis].setLeft(canvasRect.left() + fw
                    - d_data->layoutData.scale[axis].start);
                scaleRect[axis].setRight(canvasRect.right() - fw - 1
                    + d_data->layoutData.scale[axis].end);
            }
        }

        if ( scaleRect[QwtPlot::yLeft].isValid() &&
            scaleRect[QwtPlot::yRight].isValid() )
        {
            for ( int axis = QwtPlot::yLeft; axis <= QwtPlot::yRight; axis++ )
            {
                scaleRect[axis].setTop(canvasRect.top() + fw
                    - d_data->layoutData.scale[axis].start);
                scaleRect[axis].setBottom(canvasRect.bottom() - fw - 1
                    + d_data->layoutData.scale[axis].end);
            }
        }
    }
}

/*!
  \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);
    }
}