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

qwt_plot.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 #include <qlabel.h>
00011 #include <qpainter.h>
00012 #if QT_VERSION < 0x040000
00013 #include <qfocusdata.h>
00014 #else
00015 #include <qpaintengine.h>
00016 #endif
00017 #include <qapplication.h>
00018 #include <qevent.h>
00019 #include "qwt_plot.h"
00020 #include "qwt_plot_dict.h"
00021 #include "qwt_plot_layout.h"
00022 #include "qwt_rect.h"
00023 #include "qwt_scale_widget.h"
00024 #include "qwt_scale_engine.h"
00025 #include "qwt_legend.h"
00026 #include "qwt_dyngrid_layout.h"
00027 #include "qwt_plot_canvas.h"
00028 #include "qwt_paint_buffer.h"
00029 
00030 class QwtPlot::PrivateData
00031 {
00032 public:
00033     QLabel *lblTitle;
00034     QwtPlotCanvas *canvas;
00035     QwtLegend *legend;
00036     QwtPlotLayout *layout;
00037 
00038     bool autoReplot;
00039 };
00040 
00047 QwtPlot::QwtPlot(QWidget *parent):
00048     QFrame(parent)
00049 {
00050     initPlot();
00051 }
00052 
00053 
00060 QwtPlot::QwtPlot(const QString &title, QWidget *parent) :
00061     QFrame(parent)
00062 {
00063     initPlot(title);
00064 }
00065 
00067 QwtPlot::~QwtPlot()
00068 {
00069     detachItems(QwtPlotItem::Rtti_PlotItem, autoDelete());
00070 
00071     delete d_data->layout;
00072     deleteAxesData();
00073     delete d_data;
00074 }
00075 
00080 void QwtPlot::initPlot(const QString &title)
00081 {
00082     d_data = new PrivateData;
00083 
00084 #if QT_VERSION < 0x040000
00085     setWFlags(Qt::WNoAutoErase);
00086 #endif 
00087 
00088     d_data->layout = new QwtPlotLayout;
00089 
00090     d_data->autoReplot = false;
00091 
00092     d_data->lblTitle = new QLabel(title, this);
00093     d_data->lblTitle->setFont(QFont(fontInfo().family(), 14, QFont::Bold));
00094 
00095 #if QT_VERSION < 0x040000
00096     d_data->lblTitle->setAlignment(
00097         Qt::AlignCenter | Qt::WordBreak | Qt::ExpandTabs);
00098 #else
00099     // Qt::TextExpandTabs ???
00100 
00101     d_data->lblTitle->setAlignment(Qt::AlignCenter);
00102     d_data->lblTitle->setWordWrap(true);
00103 #endif
00104 
00105     d_data->legend = NULL;
00106 
00107     initAxesData();
00108 
00109     d_data->canvas = new QwtPlotCanvas(this);
00110     d_data->canvas->setFrameStyle(QFrame::Panel|QFrame::Sunken);
00111     d_data->canvas->setLineWidth(2);
00112     d_data->canvas->setMidLineWidth(0);
00113 
00114     updateTabOrder();
00115 
00116     setSizePolicy(QSizePolicy::MinimumExpanding, 
00117         QSizePolicy::MinimumExpanding);
00118 }
00119 
00123 bool QwtPlot::event(QEvent *e)
00124 {
00125     bool ok = QFrame::event(e);
00126     switch(e->type())
00127     {
00128 #if QT_VERSION < 0x040000
00129         case QEvent::LayoutHint:
00130 #else
00131         case QEvent::LayoutRequest:
00132 #endif
00133             updateLayout();
00134             break;
00135 #if QT_VERSION >= 0x040000
00136         case QEvent::PolishRequest:
00137             polish();
00138             break;
00139 #endif
00140         default:;
00141     }
00142     return ok;
00143 }
00144 
00149 void QwtPlot::autoRefresh()
00150 {
00151     if (d_data->autoReplot)
00152         replot();
00153 }
00154 
00169 void QwtPlot::setAutoReplot(bool tf)
00170 {
00171     d_data->autoReplot = tf;
00172 }
00173 
00177 bool QwtPlot::autoReplot() const
00178 {
00179     return d_data->autoReplot; 
00180 }
00181 
00186 void QwtPlot::setTitle(const QString &t)
00187 {
00188     d_data->lblTitle->setText(t);
00189 }
00190 
00195 QString QwtPlot::title() const
00196 {
00197     return d_data->lblTitle->text();
00198 }
00199 
00200 
00205 void QwtPlot::setTitleFont(const QFont &f)
00206 {
00207     d_data->lblTitle->setFont(f);
00208 }
00209 
00213 QFont QwtPlot::titleFont() const
00214 {
00215     return d_data->lblTitle->font();
00216 }
00217 
00221 QwtPlotLayout *QwtPlot::plotLayout()
00222 {
00223     return d_data->layout;
00224 }
00225 
00229 const QwtPlotLayout *QwtPlot::plotLayout() const
00230 {
00231     return d_data->layout;
00232 }
00233 
00237 QLabel *QwtPlot::titleLabel()
00238 {
00239     return d_data->lblTitle;
00240 }
00241 
00245 const QLabel *QwtPlot::titleLabel() const
00246 {
00247     return d_data->lblTitle;
00248 }
00249 
00254 QwtLegend *QwtPlot::legend()
00255 { 
00256     return d_data->legend;
00257 }   
00258 
00263 const QwtLegend *QwtPlot::legend() const
00264 { 
00265     return d_data->legend;
00266 }   
00267 
00268 
00272 QwtPlotCanvas *QwtPlot::canvas()
00273 { 
00274     return d_data->canvas;
00275 }   
00276 
00280 const QwtPlotCanvas *QwtPlot::canvas() const
00281 { 
00282     return d_data->canvas;
00283 }
00284 
00285 void QwtPlot::polish()
00286 {
00287     replot();
00288 
00289 #if QT_VERSION < 0x040000
00290     QFrame::polish();
00291 #endif
00292 }
00293 
00299 QSize QwtPlot::sizeHint() const
00300 {
00301     int dw = 0;
00302     int dh = 0;
00303     for ( int axisId = 0; axisId < axisCnt; axisId++ )
00304     {
00305         if ( axisEnabled(axisId) )
00306         {   
00307             const int niceDist = 40;
00308             const QwtScaleWidget *scaleWidget = axisWidget(axisId);
00309             const QwtScaleDiv &scaleDiv = scaleWidget->scaleDraw()->scaleDiv();
00310             const int majCnt = scaleDiv.ticks(QwtScaleDiv::MajorTick).count();
00311 
00312             if ( axisId == yLeft || axisId == yRight )
00313             {
00314                 int hDiff = (majCnt - 1) * niceDist 
00315                     - scaleWidget->minimumSizeHint().height();
00316                 if ( hDiff > dh )
00317                     dh = hDiff;
00318             }
00319             else
00320             {
00321                 int wDiff = (majCnt - 1) * niceDist 
00322                     - scaleWidget->minimumSizeHint().width();
00323                 if ( wDiff > dw )
00324                     dw = wDiff;
00325             }
00326         }
00327     }
00328     return minimumSizeHint() + QSize(dw, dh);
00329 }
00330 
00334 QSize QwtPlot::minimumSizeHint() const
00335 {
00336     QSize hint = d_data->layout->minimumSizeHint(this);
00337     hint += QSize(2 * frameWidth(), 2 * frameWidth());
00338 
00339     return hint;
00340 }
00341 
00343 void QwtPlot::resizeEvent(QResizeEvent *e)
00344 {
00345     QFrame::resizeEvent(e);
00346     updateLayout();
00347 }
00348 
00359 void QwtPlot::replot()
00360 {
00361     bool doAutoReplot = autoReplot();
00362     setAutoReplot(false);
00363 
00364     updateAxes();
00365 
00366     QwtPlotCanvas &canvas = *d_data->canvas;
00367 
00368     canvas.invalidateCache();
00369 
00370     /*
00371       In case of cached or packed painting the canvas
00372       is repainted completely and doesn't need to be erased.
00373      */
00374     const bool erase = 
00375         !canvas.testPaintAttribute(QwtPlotCanvas::PaintPacked) 
00376         && !canvas.testPaintAttribute(QwtPlotCanvas::PaintCached);
00377 
00378 #if QT_VERSION >= 0x040000
00379     const bool noBackgroundMode = canvas.testAttribute(Qt::WA_NoBackground);
00380     if ( !erase && !noBackgroundMode )
00381         canvas.setAttribute(Qt::WA_NoBackground, true);
00382 
00383     canvas.repaint(canvas.contentsRect());
00384 
00385     if ( !erase && !noBackgroundMode )
00386         canvas.setAttribute(Qt::WA_NoBackground, false);
00387 #else
00388     canvas.repaint(canvas.contentsRect(), erase);
00389 #endif
00390 
00391     setAutoReplot(doAutoReplot);
00392 }
00393 
00398 void QwtPlot::updateLayout()
00399 {
00400     d_data->layout->activate(this, contentsRect());
00401 
00402     //
00403     // resize and show the visible widgets
00404     //
00405     if (!d_data->lblTitle->text().isEmpty())
00406     {
00407         d_data->lblTitle->setGeometry(d_data->layout->titleRect());
00408         if (!d_data->lblTitle->isVisible())
00409             d_data->lblTitle->show();
00410     }
00411     else
00412         d_data->lblTitle->hide();
00413 
00414     for (int axisId = 0; axisId < axisCnt; axisId++ )
00415     {
00416         if (axisEnabled(axisId) )
00417         {
00418             axisWidget(axisId)->setGeometry(d_data->layout->scaleRect(axisId));
00419 
00420             if ( axisId == xBottom || axisId == xTop )
00421             {
00422                 QRegion r(d_data->layout->scaleRect(axisId));
00423                 if ( axisEnabled(yLeft) )
00424                     r = r.subtract(QRegion(d_data->layout->scaleRect(yLeft)));
00425                 if ( axisEnabled(yRight) )
00426                     r = r.subtract(QRegion(d_data->layout->scaleRect(yRight)));
00427                 r.translate(-d_data->layout->scaleRect(axisId).x(), 
00428                     -d_data->layout->scaleRect(axisId).y());
00429 
00430                 axisWidget(axisId)->setMask(r);
00431             }
00432             if (!axisWidget(axisId)->isVisible())
00433                 axisWidget(axisId)->show();
00434         }
00435         else
00436             axisWidget(axisId)->hide();
00437     }
00438 
00439     if ( d_data->legend )
00440     {
00441         if (d_data->legend->itemCount() > 0)
00442         {
00443             d_data->legend->setGeometry(d_data->layout->legendRect());
00444             d_data->legend->show();
00445         }
00446         else
00447             d_data->legend->hide();
00448     }
00449 
00450     d_data->canvas->setGeometry(d_data->layout->canvasRect());
00451 }
00452 
00454 
00455 void QwtPlot::updateTabOrder()
00456 {
00457 #if QT_VERSION >= 0x040000
00458     using namespace Qt; // QWidget::NoFocus/Qt::NoFocus
00459 #endif
00460     if ( !legend() || legend()->legendItems().count() == 0
00461         || d_data->canvas->focusPolicy() == NoFocus )
00462     {
00463         return;
00464     }
00465 
00466     // Depending on the position of the legend the 
00467     // tab order will be changed that the canvas is
00468     // next to the last legend item, or before
00469     // the first one. 
00470 
00471     const bool canvasFirst = 
00472         d_data->layout->legendPosition() == QwtPlot::BottomLegend ||
00473         d_data->layout->legendPosition() == QwtPlot::RightLegend;
00474 
00475     QWidget *previous = NULL; 
00476 
00477     QWidget *w;
00478 #if QT_VERSION >= 0x040000
00479     while ( nextInFocusChain() != d_data->canvas );
00480     while ( (w = nextInFocusChain()) != d_data->canvas )
00481 #else
00482     if ( focusData() == NULL )
00483         return;
00484 
00485     while ( focusData()->next() != d_data->canvas );
00486     while ( (w = focusData()->next()) != d_data->canvas )
00487 #endif
00488     {
00489         bool isLegendItem = false;
00490         if ( w->focusPolicy() != NoFocus 
00491             && w->parent() && w->parent() == d_data->legend->contentsWidget() )
00492         {
00493             isLegendItem = true;
00494         }
00495 
00496         if ( canvasFirst )
00497         {
00498             if ( isLegendItem )
00499                 break;
00500 
00501             previous = w;
00502         }
00503         else
00504         {
00505             if ( isLegendItem )
00506                 previous = w;
00507             else
00508             {
00509                 if ( previous )
00510                     break;
00511             }
00512         }
00513     }
00514 
00515     if ( previous && previous != d_data->canvas)
00516         setTabOrder(previous, d_data->canvas);
00517 }
00518 
00529 void QwtPlot::drawCanvas(QPainter *painter)
00530 {
00531     QwtArray<QwtScaleMap> maps(axisCnt);
00532     for ( int axisId = 0; axisId < axisCnt; axisId++ )
00533         maps[axisId] = canvasMap(axisId);
00534 
00535     drawItems(painter, 
00536         d_data->canvas->contentsRect(), maps, QwtPlotPrintFilter());
00537 }
00538 
00547 void QwtPlot::drawItems(QPainter *painter, const QRect &rect, 
00548         const QwtArray<QwtScaleMap> &map, 
00549         const QwtPlotPrintFilter &pfilter) const
00550 {
00551     painter->save();
00552 
00553     const QwtPlotItemList& itmList = itemList();
00554     for ( QwtPlotItemIterator it = itmList.begin();
00555         it != itmList.end(); ++it )
00556     {
00557         QwtPlotItem *item = *it;
00558         if ( item && item->isVisible() )
00559         {
00560             if ( !(pfilter.options() & QwtPlotPrintFilter::PrintGrid)
00561                 && item->rtti() == QwtPlotItem::Rtti_PlotGrid )
00562             {
00563                 continue;
00564             }
00565 
00566 #if QT_VERSION >= 0x040000
00567             const QPaintEngine *pe = painter->device()->paintEngine();
00568             if (pe->hasFeature(QPaintEngine::Antialiasing) )
00569             {
00570                 painter->setRenderHint(QPainter::Antialiasing,
00571                     item->testRenderHint(QwtPlotItem::RenderAntialiased) );
00572             }
00573 #endif
00574 
00575             item->draw(painter, 
00576                 map[item->xAxis()], map[item->yAxis()],
00577                 rect);
00578         }
00579     }
00580 
00581     painter->restore();
00582 }
00583 
00591 QwtScaleMap QwtPlot::canvasMap(int axisId) const
00592 {
00593     QwtScaleMap map;
00594     if ( !d_data->canvas )
00595         return map;
00596 
00597     map.setTransformation(axisScaleEngine(axisId)->transformation());
00598 
00599     const QwtScaleDiv *sd = axisScaleDiv(axisId);
00600     map.setScaleInterval(sd->lBound(), sd->hBound());
00601 
00602     if ( axisEnabled(axisId) )
00603     {
00604         const QwtScaleWidget *s = axisWidget(axisId);
00605         if ( axisId == yLeft || axisId == yRight )
00606         {
00607             int y = s->y() + s->startBorderDist() - d_data->canvas->y();
00608             int h = s->height() - s->startBorderDist() - s->endBorderDist();
00609             map.setPaintInterval(y + h - 1, y);
00610         }
00611         else
00612         {
00613             int x = s->x() + s->startBorderDist() - d_data->canvas->x();
00614             int w = s->width() - s->startBorderDist() - s->endBorderDist();
00615             map.setPaintInterval(x, x + w - 1);
00616         }
00617     }
00618     else
00619     {
00620         const int margin = plotLayout()->canvasMargin(axisId);
00621 
00622         const QRect &canvasRect = d_data->canvas->contentsRect();
00623         if ( axisId == yLeft || axisId == yRight )
00624         {
00625             map.setPaintInterval(canvasRect.bottom() - margin, 
00626                 canvasRect.top() + margin);
00627         }
00628         else
00629         {
00630             map.setPaintInterval(canvasRect.left() + margin, 
00631                 canvasRect.right() - margin);
00632         }
00633     }
00634     return map;
00635 }
00636 
00644 void QwtPlot::setMargin(int margin)
00645 {
00646     if ( margin < 0 )
00647         margin = 0;
00648 
00649     if ( margin != d_data->layout->margin() )
00650     {
00651         d_data->layout->setMargin(margin);
00652         updateLayout();
00653     }
00654 }
00655 
00660 int QwtPlot::margin() const
00661 {
00662     return d_data->layout->margin();
00663 }
00664 
00673 void QwtPlot::setCanvasBackground(const QColor &c)
00674 {
00675     QPalette p = d_data->canvas->palette();
00676 
00677     for ( int i = 0; i < QPalette::NColorGroups; i++ )
00678     {
00679 #if QT_VERSION < 0x040000
00680         p.setColor((QPalette::ColorGroup)i, QColorGroup::Background, c);
00681 #else
00682         p.setColor((QPalette::ColorGroup)i, QPalette::Background, c);
00683 #endif
00684     }
00685 
00686     canvas()->setPalette(p);
00687 }
00688 
00695 const QColor & QwtPlot::canvasBackground() const
00696 {
00697 #if QT_VERSION < 0x040000
00698     return canvas()->palette().color(
00699         QPalette::Normal, QColorGroup::Background);
00700 #else
00701     return canvas()->palette().color(
00702         QPalette::Normal, QPalette::Background);
00703 #endif
00704 }
00705 
00712 void QwtPlot::setCanvasLineWidth(int w)
00713 {
00714     canvas()->setLineWidth(w);
00715 }
00716  
00722 int QwtPlot::canvasLineWidth() const
00723 { 
00724     return canvas()->lineWidth();
00725 }
00726 
00731 bool QwtPlot::axisValid(int axisId)
00732 {
00733     return ((axisId >= QwtPlot::yLeft) && (axisId < QwtPlot::axisCnt));
00734 }
00735 
00741 void QwtPlot::legendItemClicked()
00742 {
00743     if ( d_data->legend && sender()->isWidgetType() )
00744     {
00745         QwtPlotItem *plotItem = d_data->legend->find((QWidget *)sender());
00746         if ( plotItem )
00747             emit legendClicked(plotItem);
00748     }
00749 }
00750 
00751 void QwtPlot::legendItemChecked(bool on)
00752 {
00753     if ( d_data->legend && sender()->isWidgetType() )
00754     {
00755         QwtPlotItem *plotItem = d_data->legend->find((QWidget *)sender());
00756         if ( plotItem )
00757             emit legendChecked(plotItem, on);
00758     }
00759 }
00760 
00762 void QwtPlot::clear()
00763 {
00764     detachItems(QwtPlotItem::Rtti_PlotCurve);
00765     detachItems(QwtPlotItem::Rtti_PlotMarker);
00766 }
00767 
00786 void QwtPlot::insertLegend(QwtLegend *legend, 
00787     QwtPlot::LegendPosition pos, double ratio)
00788 {
00789     d_data->layout->setLegendPosition(pos, ratio);
00790 
00791     if ( legend != d_data->legend )
00792     {
00793         delete d_data->legend;
00794         d_data->legend = legend;
00795 
00796         if ( d_data->legend )
00797         {
00798             if ( d_data->legend->parent() != this )
00799             {
00800 #if QT_VERSION < 0x040000
00801                 d_data->legend->reparent(this, QPoint(0, 0));
00802 #else
00803                 d_data->legend->setParent(this);
00804 #endif
00805             }
00806 
00807             const QwtPlotItemList& itmList = itemList();
00808             for ( QwtPlotItemIterator it = itmList.begin();
00809                 it != itmList.end(); ++it )
00810             {
00811                 (*it)->updateLegend(d_data->legend);
00812             }
00813 
00814             QLayout *l = d_data->legend->contentsWidget()->layout();
00815             if ( l && l->inherits("QwtDynGridLayout") )
00816             {
00817                 QwtDynGridLayout *tl = (QwtDynGridLayout *)l;
00818                 if ( d_data->layout->legendPosition() == QwtPlot::TopLegend ||
00819                     d_data->layout->legendPosition() == QwtPlot::BottomLegend )
00820                 {
00821                     tl->setMaxCols(0); // unlimited
00822                 }
00823                 else
00824                     tl->setMaxCols(1); // 1 column: align vertical
00825             }
00826         }
00827         updateTabOrder();
00828     }
00829 
00830     updateLayout();
00831 }

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