Main Page | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members | Related Pages

qwt_plot_layout.cpp

Go to the documentation of this file.
00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
00002  * Qwt Widget Library
00003  * Copyright (C) 1997   Josef Wilgen
00004  * Copyright (C) 2002   Uwe Rathmann
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the Qwt License, Version 1.0
00008  *****************************************************************************/
00009 
00010 #include <qlabel.h>
00011 #include "qwt_rect.h"
00012 #include "qwt_plot_canvas.h"
00013 #include "qwt_scale.h"
00014 #include "qwt_legend.h"
00015 #include "qwt_plot_layout.h"
00016 
00017 class QwtPlotLayoutData
00018 {
00019     friend class QwtPlotLayout;
00020 
00021 protected:
00022     QwtPlotLayoutData();
00023 
00024     void init(const QwtPlot *, const QRect &rect);
00025 
00026     struct t_legendData
00027     {
00028         int frameWidth;
00029         int vScrollBarWidth;
00030         int hScrollBarHeight;
00031         QSize hint;
00032     } legend;
00033     
00034     struct t_titleData
00035     {
00036         QFont font;
00037         QString text;
00038         int align;
00039         int frameWidth;
00040     } title;
00041 
00042     struct t_scaleData
00043     {
00044         bool isEnabled;
00045         QString title;
00046         int titleAlign;
00047         QFont titleFont;
00048         QFont scaleFont;
00049         int start;
00050         int end;
00051         int baseLineOffset;
00052         int tickOffset; 
00053         int dimWithoutTitle;
00054     } scale[QwtPlot::axisCnt];
00055 
00056     struct t_canvasData
00057     {
00058         int frameWidth;
00059     } canvas;
00060 };
00061 
00066 QwtPlotLayout::QwtPlotLayout():
00067     d_margin(0),
00068     d_spacing(5),
00069     d_canvasMargin(4)
00070 {
00071     setLegendPos(Qwt::Bottom);
00072     d_layoutData = new QwtPlotLayoutData;
00073 
00074     invalidate();
00075 }
00076 
00078 QwtPlotLayout::~QwtPlotLayout()
00079 {
00080     delete d_layoutData;
00081 }
00082 
00092 void QwtPlotLayout::setMargin(int margin)
00093 {
00094     if ( margin < 0 )
00095         margin = 0;
00096     d_margin = margin;
00097 }
00098 
00105 int QwtPlotLayout::margin() const
00106 {
00107     return d_margin;
00108 }
00109 
00118 void QwtPlotLayout::setSpacing(int spacing)
00119 {
00120     d_spacing = QMAX(0, spacing);
00121 }
00122 
00127 int QwtPlotLayout::spacing() const
00128 {
00129     return d_spacing;
00130 }
00131 
00146 void QwtPlotLayout::setLegendPos(int pos, double ratio)
00147 {
00148     if ( ratio > 1.0 )
00149         ratio = 1.0;
00150 
00151     switch(pos)
00152     {
00153         case Qwt::Top:
00154         case Qwt::Bottom:
00155             if ( ratio <= 0.0 )
00156                 ratio = 0.33;
00157             d_legendRatio = ratio;
00158             d_legendPos = pos;
00159             break;
00160         case Qwt::Left:
00161         case Qwt::Right:
00162             if ( ratio <= 0.0 )
00163                 ratio = 0.5;
00164             d_legendRatio = ratio;
00165             d_legendPos = pos;
00166             break;
00167         default:
00168             break;
00169     }
00170 }
00171 
00178 int QwtPlotLayout::legendPos() const
00179 {
00180     return d_legendPos;
00181 }
00182 
00188 double QwtPlotLayout::legendRatio() const
00189 {
00190     return d_legendRatio;
00191 }
00192 
00198 const QRect &QwtPlotLayout::titleRect() const
00199 {
00200     return d_titleRect;
00201 }
00202 
00208 const QRect &QwtPlotLayout::legendRect() const
00209 {
00210     return d_legendRect;
00211 }
00212 
00219 const QRect &QwtPlotLayout::scaleRect(int axis) const
00220 {
00221     if ( axis < 0 || axis >= QwtPlot::axisCnt )
00222     {
00223         static QRect dummyRect;
00224         return dummyRect;
00225     }
00226     return d_scaleRect[axis];
00227 }
00228 
00234 const QRect &QwtPlotLayout::canvasRect() const
00235 {
00236     return d_canvasRect;
00237 }
00238 
00243 void QwtPlotLayout::invalidate()
00244 {
00245     d_titleRect = d_legendRect = d_canvasRect = QRect();
00246     for (int axis = 0; axis < QwtPlot::axisCnt; axis++ )
00247         d_scaleRect[axis] = QRect();
00248 }
00249 
00255 QSize QwtPlotLayout::minimumSizeHint(const QwtPlot *plot) const
00256 {
00257     class ScaleData
00258     {
00259     public:
00260         ScaleData()
00261         {
00262             w = h = minLeft = minRight = tickOffset = 0;
00263         }
00264 
00265         int w;
00266         int h;
00267         int minLeft;
00268         int minRight;
00269         int tickOffset;
00270     } scaleData[QwtPlot::axisCnt];
00271 
00272     int axis;
00273     for ( axis = 0; axis < QwtPlot::axisCnt; axis++ )
00274     {
00275         const QwtScale *scl = plot->axis(axis);
00276         if ( scl )
00277         {
00278             ScaleData &sd = scaleData[axis];
00279 
00280             const QSize hint = scl->minimumSizeHint();
00281             sd.w = hint.width(); 
00282             sd.h = hint.height(); 
00283             scl->minBorderDist(sd.minLeft, sd.minRight);
00284             sd.tickOffset = scl->baseLineDist() +
00285                 scl->scaleDraw()->majTickLength();
00286         }
00287     }
00288 
00289     const int canvasBorder = plot->canvas()->frameWidth() 
00290         + d_canvasMargin + 1;
00291     for ( axis = 0; axis < QwtPlot::axisCnt; axis++ )
00292     {
00293         ScaleData &sd = scaleData[axis];
00294         if ( sd.w && (axis == QwtPlot::xBottom || axis == QwtPlot::xTop) )
00295         {
00296             if ( (sd.minLeft > canvasBorder) 
00297                 && scaleData[QwtPlot::yLeft].w )
00298             {
00299                 int shiftLeft = sd.minLeft - canvasBorder;
00300                 if ( shiftLeft > scaleData[QwtPlot::yLeft].w )
00301                     shiftLeft = scaleData[QwtPlot::yLeft].w;
00302 
00303                 sd.w -= shiftLeft;
00304             }
00305             if ( (sd.minRight > canvasBorder) 
00306                 && scaleData[QwtPlot::yRight].w )
00307             {
00308                 int shiftRight = sd.minRight - canvasBorder;
00309                 if ( shiftRight > scaleData[QwtPlot::yRight].w )
00310                     shiftRight = scaleData[QwtPlot::yRight].w;
00311 
00312                 sd.w -= shiftRight;
00313             }
00314         }
00315 
00316         if ( sd.h && (axis == QwtPlot::yLeft || axis == QwtPlot::yRight) )
00317         {
00318             if ( (sd.minLeft > canvasBorder) &&
00319                 scaleData[QwtPlot::xBottom].h )
00320             {
00321                 int shiftBottom = sd.minLeft - canvasBorder;
00322                 if ( shiftBottom > scaleData[QwtPlot::xBottom].tickOffset )
00323                     shiftBottom = scaleData[QwtPlot::xBottom].tickOffset;
00324 
00325                 sd.h -= shiftBottom;
00326             }
00327             if ( (sd.minLeft > canvasBorder) &&
00328                 scaleData[QwtPlot::xTop].h )
00329             {
00330                 int shiftTop = sd.minRight - canvasBorder;
00331                 if ( shiftTop > scaleData[QwtPlot::xTop].tickOffset )
00332                     shiftTop = scaleData[QwtPlot::xTop].tickOffset;
00333 
00334                 sd.h -= shiftTop;
00335             }
00336         }
00337     }
00338 
00339     const QwtPlotCanvas *canvas = plot->canvas();
00340 
00341     int w = scaleData[QwtPlot::yLeft].w + scaleData[QwtPlot::yRight].w
00342         + QMAX(scaleData[QwtPlot::xBottom].w, scaleData[QwtPlot::xTop].w)
00343         + 2 * (canvas->frameWidth() + 1);
00344     int h = scaleData[QwtPlot::xBottom].h + scaleData[QwtPlot::xTop].h 
00345         + QMAX(scaleData[QwtPlot::yLeft].h, scaleData[QwtPlot::yRight].h)
00346         + 2 * (canvas->frameWidth() + 1);
00347 
00348     const QLabel *title = plot->titleLabel();
00349     if (title && !title->text().isEmpty())
00350     {
00351         // If only QwtPlot::yLeft or QwtPlot::yRight is showing, 
00352         // we center on the plot canvas.
00353         const bool centerOnCanvas = plot->axis(QwtPlot::yLeft) == 0 
00354             || plot->axis(QwtPlot::yRight) == 0;
00355 
00356         int titleW = w;
00357         if ( centerOnCanvas )
00358         {
00359             titleW -= scaleData[QwtPlot::yLeft].w 
00360                 + scaleData[QwtPlot::yRight].w;
00361         }
00362 
00363         int titleH = title->heightForWidth(titleW);
00364         if ( titleH > titleW ) // Compensate for a long title
00365         {
00366             w = titleW = titleH;
00367             if ( centerOnCanvas )
00368             {
00369                 w += scaleData[QwtPlot::yLeft].w
00370                     + scaleData[QwtPlot::yRight].w;
00371             }
00372 
00373             titleH = title->heightForWidth(titleW);
00374         }
00375         h += titleH + d_spacing;
00376     }
00377 
00378     // Compute the legend contribution
00379 
00380     const QwtLegend *legend = plot->legend();
00381     if ( legend && !legend->isEmpty() )
00382     {
00383         if ( d_legendPos == Qwt::Left || d_legendPos == Qwt::Right )
00384         {
00385             int legendW = legend->sizeHint().width();
00386             int legendH = legend->heightForWidth(legendW); 
00387 
00388             if ( legend->frameWidth() > 0 )
00389                 w += d_spacing;
00390 
00391             if ( legendH > h )
00392                 legendW += legend->verticalScrollBar()->sizeHint().height();
00393 
00394             if ( d_legendRatio < 1.0 )
00395                 legendW = QMIN(legendW, int(w / (1.0 - d_legendRatio)));
00396 
00397             w += legendW;
00398         }
00399         else // Qwt::Top, Qwt::Bottom
00400         {
00401             int legendW = QMIN(legend->sizeHint().width(), w);
00402             int legendH = legend->heightForWidth(legendW); 
00403 
00404             if ( legend->frameWidth() > 0 )
00405                 h += d_spacing;
00406 
00407             if ( d_legendRatio < 1.0 )
00408                 legendH = QMIN(legendH, int(h / (1.0 - d_legendRatio)));
00409             
00410             h += legendH;
00411         }
00412     }
00413 
00414     w += 2 * d_margin;
00415     h += 2 * d_margin;
00416 
00417     return QSize( w, h );
00418 }
00419 
00427 QRect QwtPlotLayout::layoutLegend(int options, 
00428     const QRect &rect) const
00429 {
00430     const QSize hint(d_layoutData->legend.hint);
00431 
00432     int dim;
00433     if ( d_legendPos == Qwt::Left || d_legendPos == Qwt::Right )
00434     {
00435         // We don't allow vertical legends to take more than
00436         // half of the available space.
00437 
00438         dim = QMIN(hint.width(), int(rect.width() * d_legendRatio));
00439 
00440         if ( !(options & IgnoreScrollbars) )
00441         {
00442             if ( hint.height() > rect.height() )
00443             {
00444                 // The legend will need additional
00445                 // space for the vertical scrollbar. 
00446 
00447                 dim += d_layoutData->legend.vScrollBarWidth;
00448             }
00449         }
00450     }
00451     else
00452     {
00453         dim = QMIN(hint.height(), int(rect.height() * d_legendRatio));
00454         dim = QMAX(dim, d_layoutData->legend.hScrollBarHeight);
00455     }
00456 
00457     QRect legendRect = rect;
00458     switch(d_legendPos)
00459     {
00460         case Qwt::Left:
00461             legendRect.setWidth(dim);
00462             break;
00463         case Qwt::Right:
00464             legendRect.setX(rect.right() - dim + 1);
00465             legendRect.setWidth(dim);
00466             break;
00467         case Qwt::Top:
00468             legendRect.setHeight(dim);
00469             break;
00470         case Qwt::Bottom:
00471             legendRect.setY(rect.bottom() - dim + 1);
00472             legendRect.setHeight(dim);
00473             break;
00474     }
00475 
00476     return legendRect;
00477 }
00478 
00485 QRect QwtPlotLayout::alignLegend(const QRect &canvasRect, 
00486     const QRect &legendRect) const
00487 {
00488     QRect alignedRect = legendRect;
00489 
00490     if ( d_legendPos == Qwt::Bottom || d_legendPos == Qwt::Top )
00491     {
00492         if ( d_layoutData->legend.hint.width() < canvasRect.width() )
00493         {
00494             alignedRect.setX(canvasRect.x());
00495             alignedRect.setWidth(canvasRect.width());
00496         }
00497     }
00498     else
00499     {
00500         if ( d_layoutData->legend.hint.height() < canvasRect.height() )
00501         {
00502             alignedRect.setY(canvasRect.y());
00503             alignedRect.setHeight(canvasRect.height());
00504         }
00505     }
00506 
00507     return alignedRect;
00508 }
00509 
00519 void QwtPlotLayout::expandLineBreaks(int options, const QRect &rect, 
00520     int &dimTitle, int dimAxis[QwtPlot::axisCnt]) const
00521 {
00522     dimTitle = 0;
00523     for ( int i = 0; i < QwtPlot::axisCnt; i++ )
00524         dimAxis[i] = 0;
00525 
00526     bool done = FALSE;
00527     while (!done)
00528     {
00529         done = TRUE;
00530 
00531         // the size for the 4 axis depend on each other. Expanding
00532         // the height of a horizontal axis will shrink the height
00533         // for the vertical axis, shrinking the height of a vertical
00534         // axis will result in a line break what will expand the
00535         // width and results in shrinking the width of a horizontal
00536         // axis what might result in a line break of a horizontal
00537         // axis ... . So we loop as long until no size changes.
00538 
00539         if ( !d_layoutData->title.text.isEmpty())
00540         {
00541             int w = rect.width();
00542 
00543             if ( d_layoutData->scale[QwtPlot::yLeft].isEnabled
00544                 != d_layoutData->scale[QwtPlot::yRight].isEnabled )
00545             {
00546                 // center to the canvas
00547                 w -= dimAxis[QwtPlot::yLeft] + dimAxis[QwtPlot::yRight]; 
00548             }
00549 
00550             const QFontMetrics fm(d_layoutData->title.font);
00551             int d = fm.boundingRect(0, 0, w, QCOORD_MAX,
00552                 d_layoutData->title.align, 
00553                 d_layoutData->title.text).height();
00554 
00555             if ( !(options & IgnoreFrames) )
00556                 d += 2 * d_layoutData->title.frameWidth;
00557 
00558             if ( d > dimTitle )
00559             {
00560                 dimTitle = d;
00561                 done = FALSE;
00562             }
00563         }
00564 
00565         for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
00566         {
00567             const struct QwtPlotLayoutData::t_scaleData &scaleData = 
00568                 d_layoutData->scale[axis];
00569 
00570             if (scaleData.isEnabled)
00571             {
00572                 int length;
00573                 if ( axis == QwtPlot::xTop || axis == QwtPlot::xBottom )
00574                 {
00575                     length = rect.width() - dimAxis[QwtPlot::yLeft] 
00576                         - dimAxis[QwtPlot::yRight];
00577                     length += QMIN(dimAxis[QwtPlot::yLeft], 
00578                         scaleData.start);
00579                     length += QMIN(dimAxis[QwtPlot::yRight], 
00580                         scaleData.end);
00581                 }
00582                 else // QwtPlot::yLeft, QwtPlot::yRight
00583                 {
00584                     length = rect.height() - dimAxis[QwtPlot::xTop] 
00585                         - dimAxis[QwtPlot::xBottom];
00586 
00587                     if ( dimAxis[QwtPlot::xBottom] > 0 )
00588                     {
00589                         length += QMIN(
00590                             d_layoutData->scale[QwtPlot::xBottom].tickOffset, 
00591                             scaleData.start);
00592                     }
00593                     if ( dimAxis[QwtPlot::xTop] > 0 )
00594                     {
00595                         length += QMIN(
00596                             d_layoutData->scale[QwtPlot::xTop].tickOffset, 
00597                             scaleData.end);
00598                     }
00599 
00600                     if ( dimTitle > 0 )
00601                         length -= dimTitle + d_spacing;
00602                 }
00603 
00604                 int d = scaleData.dimWithoutTitle;
00605                 if ( !scaleData.title.isEmpty() )
00606                 {
00607                     const QFontMetrics fm(scaleData.titleFont);
00608                     d += fm.boundingRect(
00609                         0, 0, length, QCOORD_MAX, 
00610                         scaleData.titleAlign, scaleData.title).height();
00611                 }
00612 
00613                 if ( options & AlignScales )
00614                     d -= scaleData.baseLineOffset;
00615 
00616                 if ( d > dimAxis[axis] )
00617                 {
00618                     dimAxis[axis] = d;
00619                     done = FALSE;
00620                 }
00621             }
00622         }
00623     }
00624 }
00625 
00631 void QwtPlotLayout::alignScales(int options,
00632     QRect scaleRect[QwtPlot::axisCnt]) const
00633 {
00634     int backboneOffset = d_canvasMargin;
00635     if ( !(options & IgnoreFrames) )
00636         backboneOffset += d_layoutData->canvas.frameWidth;
00637 
00638     for (int axis = 0; axis < QwtPlot::axisCnt; axis++ )
00639     {
00640         if ( !scaleRect[axis].isValid() )
00641             continue;
00642 
00643         const int startDist = d_layoutData->scale[axis].start;
00644         const int endDist = d_layoutData->scale[axis].end;
00645 
00646         QRect &axisRect = scaleRect[axis];
00647 
00648         if ( axis == QwtPlot::xTop || axis == QwtPlot::xBottom )
00649         {
00650             int minLeft = axisRect.left();
00651             if ( scaleRect[QwtPlot::yLeft].isValid() )
00652                 minLeft = scaleRect[QwtPlot::yLeft].left();
00653 
00654             int left = axisRect.left() + backboneOffset - startDist;
00655             axisRect.setLeft(QMAX(left, minLeft));
00656 
00657             int maxRight = axisRect.right();
00658             if ( scaleRect[QwtPlot::yRight].isValid() )
00659                 maxRight = scaleRect[QwtPlot::yRight].right();
00660 
00661             int right = axisRect.right() - backboneOffset + endDist;
00662             axisRect.setRight(QMIN(right, maxRight));
00663         }
00664         else // QwtPlot::yLeft, QwtPlot::yRight
00665         {
00666             int maxBottom = axisRect.bottom();
00667             if ( scaleRect[QwtPlot::xBottom].isValid() )
00668             {
00669                 maxBottom = scaleRect[QwtPlot::xBottom].top() + 
00670                     d_layoutData->scale[QwtPlot::xBottom].tickOffset;
00671             }
00672 
00673             int bottom = axisRect.bottom() - backboneOffset + startDist;
00674             axisRect.setBottom(QMIN(bottom, maxBottom));
00675         
00676             int minTop = axisRect.top();
00677             if ( scaleRect[QwtPlot::xTop].isValid() )
00678             {
00679                 minTop = scaleRect[QwtPlot::xTop].bottom() -
00680                     d_layoutData->scale[QwtPlot::xTop].tickOffset;
00681             }
00682 
00683             int top = axisRect.top() + backboneOffset - endDist;
00684             axisRect.setTop(QMAX(top, minTop));
00685         }
00686     }
00687 }
00688 
00701 void QwtPlotLayout::activate(const QwtPlot *plot,
00702     const QRect &plotRect, int options) 
00703 {
00704     invalidate();
00705 
00706     QRect rect(plotRect);  // undistributed rest of the plot rect
00707 
00708     if ( !(options & IgnoreMargin) )
00709     {
00710         // subtract the margin
00711 
00712         rect.setRect(
00713             rect.x() + d_margin, 
00714             rect.y() + d_margin,
00715             rect.width() - 2 * d_margin, 
00716             rect.height() - 2 * d_margin
00717         );
00718     }
00719 
00720     // We extract all layout relevant data from the widgets,
00721     // filter them through pfilter and save them to d_layoutData.
00722 
00723     d_layoutData->init(plot, rect);
00724 
00725     if (!(options & IgnoreLegend)
00726         && plot->legend() && !plot->legend()->isEmpty() )
00727     {
00728         d_legendRect = layoutLegend(options, rect);
00729 
00730         // subtract d_legendRect from rect
00731 
00732         const QRegion region(rect);
00733         rect = region.subtract(d_legendRect).boundingRect(); 
00734 
00735         if ( d_layoutData->legend.frameWidth && 
00736             !(options & IgnoreFrames ) )
00737         {
00738             // In case of a frame we have to insert a spacing.
00739             // Otherwise the leading of the font separates
00740             // legend and scale/canvas
00741 
00742             switch(d_legendPos)
00743             {
00744                 case Qwt::Left:
00745                     rect.setLeft(rect.left() + d_spacing);
00746                     break;
00747                 case Qwt::Right:
00748                     rect.setRight(rect.right() - d_spacing);
00749                     break;
00750                 case Qwt::Top:
00751                     rect.setTop(rect.top() + d_spacing);
00752                     break;
00753                 case Qwt::Bottom:
00754                     rect.setBottom(rect.bottom() - d_spacing);
00755                     break;
00756             }
00757         }
00758     }
00759 
00760     /*
00761      +---+-----------+---+
00762      |       Title       |
00763      +---+-----------+---+
00764      |   |   Axis    |   |
00765      +---+-----------+---+
00766      | A |           | A |
00767      | x |  Canvas   | x |
00768      | i |           | i |
00769      | s |           | s |
00770      +---+-----------+---+
00771      |   |   Axis    |   |
00772      +---+-----------+---+
00773     */
00774 
00775 
00776     // axes and title include text labels. The height of each
00777     // label depends on its line breaks, that depend on the width
00778     // for the label. A line break in a horizontal text will reduce
00779     // the available width for vertical texts and vice versa. 
00780     // expandLineBreaks finds the height/width for title and axes
00781     // including all line breaks.
00782 
00783     int dimTitle, dimAxes[QwtPlot::axisCnt];
00784     expandLineBreaks(options, rect, dimTitle, dimAxes);
00785 
00786     if (dimTitle > 0 )
00787     {
00788         d_titleRect = QRect(rect.x(), rect.y(),
00789             rect.width(), dimTitle);
00790 
00791         if ( d_layoutData->scale[QwtPlot::yLeft].isEnabled !=
00792             d_layoutData->scale[QwtPlot::yRight].isEnabled )
00793         {
00794             // if only one of the y axes is missing we align
00795             // the title centered to the canvas
00796 
00797             d_titleRect.setX(rect.x() + dimAxes[QwtPlot::yLeft]);
00798             d_titleRect.setWidth(rect.width() 
00799                 - dimAxes[QwtPlot::yLeft] - dimAxes[QwtPlot::yRight]);
00800         }
00801 
00802         // subtract title 
00803         rect.setTop(rect.top() + dimTitle + d_spacing);
00804     }
00805 
00806     d_canvasRect.setRect(
00807         rect.x() + dimAxes[QwtPlot::yLeft],
00808         rect.y() + dimAxes[QwtPlot::xTop],
00809         rect.width() - dimAxes[QwtPlot::yRight] - dimAxes[QwtPlot::yLeft],
00810         rect.height() - dimAxes[QwtPlot::xBottom] - dimAxes[QwtPlot::xTop]);
00811 
00812     for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
00813     {
00814         // set the rects for the axes
00815 
00816         if ( dimAxes[axis] )
00817         {
00818             int dim = dimAxes[axis];
00819             QRect &scaleRect = d_scaleRect[axis];
00820 
00821             scaleRect = d_canvasRect;
00822             switch(axis)
00823             {
00824                 case QwtPlot::yLeft:
00825                     scaleRect.setX(d_canvasRect.left() - dim);
00826                     scaleRect.setWidth(dim);
00827                     break;
00828                 case QwtPlot::yRight:
00829                     scaleRect.setX(d_canvasRect.right() + 1);
00830                     scaleRect.setWidth(dim);
00831                     break;
00832                 case QwtPlot::xBottom:
00833                     scaleRect.setY(d_canvasRect.bottom() + 1);
00834                     scaleRect.setHeight(dim);
00835                     break;
00836                 case QwtPlot::xTop:
00837                     scaleRect.setY(d_canvasRect.top() - dim);
00838                     scaleRect.setHeight(dim);
00839                     break;
00840             }
00841             scaleRect = scaleRect.normalize();
00842         }
00843     }
00844 
00845     // +---+-----------+---+
00846     // |  <-   Axis   ->   |
00847     // +-^-+-----------+-^-+
00848     // | | |           | | |
00849     // |   |           |   |
00850     // | A |           | A |
00851     // | x |  Canvas   | x |
00852     // | i |           | i |
00853     // | s |           | s |
00854     // |   |           |   |
00855     // | | |           | | |
00856     // +-V-+-----------+-V-+
00857     // |   <-  Axis   ->   |
00858     // +---+-----------+---+
00859 
00860     // The ticks of the axes - not the labels above - should
00861     // be aligned to the canvas. So we try to use the empty
00862     // corners to extend the axes, so that the label texts
00863     // left/right of the min/max ticks are moved into them.
00864  
00865     alignScales(options, d_scaleRect);
00866 
00867     if (!d_legendRect.isEmpty() )
00868     {
00869         // We prefer to align the legend to the canvas - not to
00870         // the complete plot - if possible.
00871 
00872         d_legendRect = alignLegend(d_canvasRect, d_legendRect);
00873     }
00874 }
00875 
00876 QwtPlotLayoutData::QwtPlotLayoutData()
00877 {
00878 }
00879 
00880 /*
00881   Extract all layout relevant data from the plot components
00882 */
00883 
00884 void QwtPlotLayoutData::init(const QwtPlot *plot, const QRect &rect)
00885 {
00886     // legend
00887 
00888     legend.frameWidth = plot->legend()->frameWidth();
00889     legend.vScrollBarWidth = 
00890         plot->legend()->verticalScrollBar()->sizeHint().width();
00891     legend.hScrollBarHeight = 
00892         plot->legend()->horizontalScrollBar()->sizeHint().width();
00893 
00894     const QSize hint = plot->legend()->sizeHint();
00895 
00896     int w = QMIN(hint.width(), rect.width());
00897     int h = plot->legend()->heightForWidth(w);
00898     if ( h == 0 )
00899         h = hint.height();
00900 
00901     if ( h > rect.height() )
00902         w += legend.vScrollBarWidth;
00903 
00904     legend.hint = QSize(w, h);
00905 
00906     // title 
00907 
00908     title.frameWidth = 0;
00909     title.text = QString::null;
00910 
00911     if (plot->titleLabel() && !plot->titleLabel()->text().isEmpty())
00912     {
00913         title.align = plot->titleLabel()->alignment();
00914         title.font = plot->titleLabel()->font();
00915         title.text = plot->titleLabel()->text();
00916         title.frameWidth = plot->titleLabel()->frameWidth();
00917     }
00918 
00919     // scales 
00920 
00921     for (int axis = 0; axis < QwtPlot::axisCnt; axis++ )
00922     {
00923         const QwtScale *sd = plot->axis(axis);
00924         if ( sd )
00925         {
00926             scale[axis].isEnabled = TRUE;
00927 
00928             scale[axis].title = sd->title();
00929             scale[axis].titleAlign = sd->titleAlignment();
00930             scale[axis].titleFont = sd->titleFont();
00931 
00932             scale[axis].scaleFont = sd->font();
00933 
00934             scale[axis].start = sd->startBorderDist();
00935             scale[axis].end = sd->endBorderDist();
00936 
00937             scale[axis].baseLineOffset = sd->baseLineDist();
00938             scale[axis].tickOffset = sd->baseLineDist() + 
00939                 (int)sd->scaleDraw()->majTickLength();
00940 
00941             scale[axis].dimWithoutTitle = sd->dimForLength(QCOORD_MAX,
00942                 scale[axis].titleFont, scale[axis].scaleFont);
00943 
00944             if ( !sd->title().isEmpty() )
00945             {
00946                 const QFontMetrics fm(scale[axis].titleFont);
00947                 scale[axis].dimWithoutTitle -= fm.boundingRect(
00948                     0, 0, QCOORD_MAX, QCOORD_MAX, sd->titleAlignment(),
00949                     sd->title()).height();
00950             }
00951         }
00952         else
00953         {
00954             scale[axis].title = QString::null;
00955             scale[axis].isEnabled = FALSE;
00956             scale[axis].start = 0;
00957             scale[axis].end = 0;
00958             scale[axis].baseLineOffset = 0;
00959             scale[axis].tickOffset = 0;
00960             scale[axis].dimWithoutTitle = 0;
00961         }
00962     }
00963 
00964     // canvas 
00965 
00966     canvas.frameWidth = plot->canvas()->frameWidth();
00967 }

Generated on Fri Nov 7 14:11:45 2003 for Qwt Developer's Guide by doxygen 1.3.2