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

qwt_plot_print.cpp

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 // vim: expandtab
00011 
00012 #include <qlabel.h>
00013 #include <qpainter.h>
00014 #if QT_VERSION < 0x040000
00015 #include <qpaintdevicemetrics.h>
00016 #endif
00017 #include "qwt_painter.h"
00018 #include "qwt_legend_item.h"
00019 #include "qwt_plot.h"
00020 #include "qwt_plot_canvas.h"
00021 #include "qwt_plot_layout.h"
00022 #include "qwt_legend.h"
00023 #include "qwt_rect.h"
00024 #include "qwt_dyngrid_layout.h"
00025 #include "qwt_scale_widget.h"
00026 #include "qwt_scale_engine.h"
00027 #include "qwt_text.h"
00028 #include "qwt_math.h"
00029 
00076 void QwtPlot::print(QPaintDevice &paintDev,
00077    const QwtPlotPrintFilter &pfilter) const
00078 {
00079 #if QT_VERSION < 0x040000
00080     QPaintDeviceMetrics mpr(&paintDev);
00081     int w = mpr.width();
00082     int h = mpr.height();
00083 #else
00084     int w = paintDev.width();
00085     int h = paintDev.height();
00086 #endif
00087 
00088     QRect rect(0, 0, w, h);
00089     double aspect = double(rect.width())/double(rect.height());
00090     if ((aspect < 1.0))
00091         rect.setHeight(int(aspect*rect.width()));
00092 
00093     QPainter p(&paintDev);
00094     print(&p, rect, pfilter);
00095 }
00096 
00106 void QwtPlot::print(QPainter *painter, const QRect &plotRect,
00107         const QwtPlotPrintFilter &pfilter) const
00108 {
00109     int axisId;
00110 
00111     if ( painter == 0 || !painter->isActive() ||
00112             !plotRect.isValid() || size().isNull() )
00113        return;
00114 
00115     painter->save();
00116 
00117     // All paint operations need to be scaled according to
00118     // the paint device metrics. 
00119 
00120     QwtPainter::setMetricsMap(this, painter->device());
00121     const QwtMetricsMap &metricsMap = QwtPainter::metricsMap();
00122 
00123     // It is almost impossible to integrate into the Qt layout
00124     // framework, when using different fonts for printing
00125     // and screen. To avoid writing different and Qt unconform
00126     // layout engines we change the widget attributes, print and 
00127     // reset the widget attributes again. This way we produce a lot of
00128     // useless layout events ...
00129 
00130     pfilter.apply((QwtPlot *)this);
00131 
00132     int baseLineDists[QwtPlot::axisCnt];
00133     if ( !(pfilter.options() & QwtPlotPrintFilter::PrintCanvasBackground) )
00134     {
00135         // In case of no background we set the backbone of
00136         // the scale on the frame of the canvas.
00137 
00138         for (axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
00139         {
00140             QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId);
00141             if ( scaleWidget )
00142             {
00143                 baseLineDists[axisId] = scaleWidget->baseLineDist();
00144                 scaleWidget->setBaselineDist(0);
00145             }
00146         }
00147     }
00148     // Calculate the layout for the print.
00149 
00150     int layoutOptions = QwtPlotLayout::IgnoreScrollbars 
00151         | QwtPlotLayout::IgnoreFrames | QwtPlotLayout::AlignScales;
00152     if ( !(pfilter.options() & QwtPlotPrintFilter::PrintMargin) )
00153         layoutOptions |= QwtPlotLayout::IgnoreMargin;
00154     if ( !(pfilter.options() & QwtPlotPrintFilter::PrintLegend) )
00155         layoutOptions |= QwtPlotLayout::IgnoreLegend;
00156 
00157     ((QwtPlot *)this)->plotLayout()->activate(this, 
00158         QwtPainter::metricsMap().deviceToLayout(plotRect), 
00159         layoutOptions);
00160 
00161     if ((pfilter.options() & QwtPlotPrintFilter::PrintTitle)
00162         && (!titleLabel()->text().isEmpty()))
00163     {
00164         printTitle(painter, plotLayout()->titleRect());
00165     }
00166 
00167     if ( (pfilter.options() & QwtPlotPrintFilter::PrintLegend)
00168         && !legend()->isEmpty() )
00169     {
00170         printLegend(painter, plotLayout()->legendRect());
00171     }
00172 
00173     for ( axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
00174     {
00175         QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId);
00176         if (scaleWidget)
00177         {
00178             int baseDist = scaleWidget->baseLineDist();
00179 
00180             int startDist, endDist;
00181             scaleWidget->minBorderDist(startDist, endDist);
00182 
00183             printScale(painter, axisId, startDist, endDist,
00184                 baseDist, plotLayout()->scaleRect(axisId));
00185         }
00186     }
00187 
00188     const QRect canvasRect = metricsMap.layoutToDevice(plotLayout()->canvasRect());
00189 
00190     // When using QwtPainter all sizes where computed in pixel
00191     // coordinates and scaled by QwtPainter later. This limits
00192     // the precision to screen resolution. A much better solution
00193     // is to scale the maps and print in unlimited resolution.
00194 
00195     QwtArray<QwtScaleMap> map(axisCnt);
00196     for (axisId = 0; axisId < axisCnt; axisId++)
00197     {
00198         map[axisId].setTransformation(axisScaleEngine(axisId)->transformation());
00199 
00200         const QwtScaleDiv &scaleDiv = *axisScaleDiv(axisId);
00201         map[axisId].setScaleInterval(scaleDiv.lBound(), scaleDiv.hBound());
00202 
00203         double from, to;
00204         if ( axisEnabled(axisId) )
00205         {
00206             const int sDist = axisWidget(axisId)->startBorderDist();
00207             const int eDist = axisWidget(axisId)->endBorderDist();
00208             const QRect &scaleRect = plotLayout()->scaleRect(axisId);
00209 
00210             if ( axisId == xTop || axisId == xBottom )
00211             {
00212                 from = metricsMap.layoutToDeviceX(scaleRect.left() + sDist);
00213                 to = metricsMap.layoutToDeviceX(scaleRect.right() - eDist);
00214             }
00215             else
00216             {
00217                 from = metricsMap.layoutToDeviceY(scaleRect.bottom() - sDist);
00218                 to = metricsMap.layoutToDeviceY(scaleRect.top() + eDist);
00219             }
00220         }
00221         else
00222         {
00223             const int margin = plotLayout()->canvasMargin(axisId);
00224 
00225             const QRect &canvasRect = plotLayout()->canvasRect();
00226             if ( axisId == yLeft || axisId == yRight )
00227             {
00228                 from = metricsMap.layoutToDeviceX(canvasRect.bottom() - margin);
00229                 to = metricsMap.layoutToDeviceX(canvasRect.top() + margin);
00230             }
00231             else
00232             {
00233                 from = metricsMap.layoutToDeviceY(canvasRect.left() + margin);
00234                 to = metricsMap.layoutToDeviceY(canvasRect.right() - margin);
00235             }
00236         }
00237         map[axisId].setPaintXInterval(from, to);
00238     }
00239 
00240 
00241     // The maps are already scaled. 
00242     QwtPainter::setMetricsMap(painter->device(), painter->device());
00243 
00244     printCanvas(painter, canvasRect, map, pfilter);
00245 
00246     QwtPainter::resetMetricsMap();
00247 
00248     ((QwtPlot *)this)->plotLayout()->invalidate();
00249 
00250     // reset all widgets with their original attributes.
00251     if ( !(pfilter.options() & QwtPlotPrintFilter::PrintCanvasBackground) )
00252     {
00253         // restore the previous base line dists
00254 
00255         for (axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
00256         {
00257             QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId);
00258             if ( scaleWidget  )
00259                 scaleWidget->setBaselineDist(baseLineDists[axisId]);
00260         }
00261     }
00262 
00263     pfilter.reset((QwtPlot *)this);
00264 
00265     painter->restore();
00266 }
00267 
00275 void QwtPlot::printTitle(QPainter *painter, const QRect &rect) const
00276 {
00277     const QLabel *label = titleLabel();
00278 
00279     const QColor color =
00280 #if QT_VERSION >= 0x040000
00281         label->palette().color(QPalette::Active, QPalette::Foreground);
00282 #else
00283         label->palette().color(QPalette::Active, QColorGroup::Foreground);
00284 #endif
00285 
00286     QwtText *text = QwtText::makeText(
00287         label->text(), label->textFormat(),
00288         label->alignment(), label->font(), color); 
00289 
00290     text->draw(painter, rect);
00291     delete text;
00292 }
00293 
00301 void QwtPlot::printLegend(QPainter *painter, const QRect &rect) const
00302 {
00303     if ( !legend() || legend()->isEmpty() )
00304         return;
00305 
00306     QLayout *l = legend()->contentsWidget()->layout();
00307     if ( l == 0 || !l->inherits("QwtDynGridLayout") )
00308         return;
00309 
00310     QwtDynGridLayout *legendLayout = (QwtDynGridLayout *)l;
00311 
00312     uint numCols = legendLayout->columnsForWidth(rect.width());
00313 #if QT_VERSION < 0x040000
00314     QValueList<QRect> itemRects = 
00315         legendLayout->layoutItems(rect, numCols);
00316 #else
00317     QList<QRect> itemRects = 
00318         legendLayout->layoutItems(rect, numCols);
00319 #endif
00320 
00321     int index = 0;
00322 
00323 #if QT_VERSION < 0x040000
00324     QLayoutIterator layoutIterator = legendLayout->iterator();
00325     for ( QLayoutItem *item = layoutIterator.current(); 
00326         item != 0; item = ++layoutIterator)
00327     {
00328 #else
00329     for ( int i = 0; i < legendLayout->count(); i++ )
00330     {
00331         QLayoutItem *item = legendLayout->itemAt(i);
00332 #endif
00333         QWidget *w = item->widget();
00334         if ( w )
00335         {
00336             painter->save();
00337             painter->setClipping(true);
00338             QwtPainter::setClipRect(painter, itemRects[index]);
00339 
00340             printLegendItem(painter, w, itemRects[index]);
00341 
00342             index++;
00343             painter->restore();
00344         }
00345     }
00346 }
00347 
00356 void QwtPlot::printLegendItem(QPainter *painter, 
00357     const QWidget *w, const QRect &rect) const
00358 {
00359     if ( w->inherits("QwtLegendItem") )
00360     {
00361         QwtLegendItem *item = (QwtLegendItem *)w;
00362 
00363         painter->setFont(item->font());
00364         item->drawItem(painter, rect);
00365     }
00366 }
00367 
00380 void QwtPlot::printScale(QPainter *painter,
00381     int axisId, int startDist, int endDist, int baseDist, 
00382     const QRect &rect) const
00383 {
00384     if (!axisEnabled(axisId))
00385         return;
00386 
00387     QwtScaleDraw::Orientation o;
00388     int x, y, w;
00389 
00390     switch(axisId)
00391     {
00392         case yLeft:
00393         {
00394             x = rect.right() - baseDist;
00395             y = rect.y() + startDist;
00396             w = rect.height() - startDist - endDist;
00397             o = QwtScaleDraw::Left;
00398             break;
00399         }
00400         case yRight:
00401         {
00402             x = rect.left() + baseDist;
00403             y = rect.y() + startDist;
00404             w = rect.height() - startDist - endDist;
00405             o = QwtScaleDraw::Right;
00406             break;
00407         }
00408         case xTop:
00409         {
00410             x = rect.left() + startDist;
00411             y = rect.bottom() - baseDist;
00412             w = rect.width() - startDist - endDist;
00413             o = QwtScaleDraw::Top;
00414             break;
00415         }
00416         case xBottom:
00417         {
00418             x = rect.left() + startDist;
00419             y = rect.top() + baseDist;
00420             w = rect.width() - startDist - endDist;
00421             o = QwtScaleDraw::Bottom;
00422             break;
00423         }
00424         default:
00425             return;
00426     }
00427 
00428     const QwtScaleWidget *scaleWidget = axisWidget(axisId);
00429     scaleWidget->drawTitle(painter, o, rect);
00430 
00431     painter->save();
00432     painter->setFont(scaleWidget->font());
00433 
00434     QwtScaleDraw *sd = (QwtScaleDraw *)scaleWidget->scaleDraw();
00435     int xSd = sd->x();
00436     int ySd = sd->y();
00437     int lengthSd = sd->length();
00438 
00439     sd->setGeometry(x, y, w, o);
00440 #if QT_VERSION < 0x040000
00441     sd->draw(painter, scaleWidget->palette().active());
00442 #else
00443     QPalette palette = scaleWidget->palette();
00444     palette.setCurrentColorGroup(QPalette::Active);
00445     sd->draw(painter, palette);
00446 #endif
00447     sd->setGeometry(xSd, ySd, lengthSd, o); // reset previous values
00448     painter->restore();
00449 }
00450 
00461 void QwtPlot::printCanvas(QPainter *painter, const QRect &canvasRect,
00462     const QwtArray<QwtScaleMap> &map, const QwtPlotPrintFilter &pfilter) const
00463 {
00464     if ( pfilter.options() & QwtPlotPrintFilter::PrintCanvasBackground )
00465     {
00466         painter->setPen(Qt::NoPen);
00467 
00468         QBrush bgBrush;
00469 #if QT_VERSION >= 0x040000
00470             bgBrush = canvas()->palette().brush(backgroundRole());
00471 #else
00472         QColorGroup::ColorRole role =
00473             QPalette::backgroundRoleFromMode( backgroundMode() ); 
00474         bgBrush = canvas()->colorGroup().brush( role );
00475 #endif
00476         painter->setBrush(bgBrush);
00477         QwtPainter::drawRect(painter, QRect(canvasRect.x(), canvasRect.y(), 
00478             canvasRect.width() - 1, canvasRect.height() - 1) );
00479     }
00480     else
00481     {
00482 #ifdef __GNUC__
00483 #warning why different recs ?
00484 #endif
00485         QwtPainter::drawRect(painter, canvasRect.x() - 1, canvasRect.y() - 1,
00486             canvasRect.width() + 1, canvasRect.height() + 1);
00487     }
00488 
00489     painter->setClipping(true);
00490     QwtPainter::setClipRect(painter, canvasRect);
00491 
00492     drawItems(painter, canvasRect, map, pfilter);
00493 }

Generated on Wed Aug 31 23:02:29 2005 for Qwt User's Guide by  doxygen 1.4.1