# qwt_plot_canvas.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 <qpainter.h>
    00013 #include <qstyle.h>
    00014 #if QT_VERSION >= 0x040000
    00015 #include <qstyleoption.h>
    00016 #include <qpaintengine.h>
    00017 #ifdef Q_WS_X11
    00018 #include <qx11info_x11.h>
    00019 #endif
    00020 #endif
    00021 #include <qevent.h>
    00022 #include "qwt_painter.h"
    00023 #include "qwt_math.h"
    00024 #include "qwt_plot.h"
    00025 #include "qwt_paint_buffer.h"
    00026 #include "qwt_plot_canvas.h"
    00027
    00028 class QwtPlotCanvas::PrivateData
    00029 {
    00030 public:
    00031     PrivateData():
    00032         focusIndicator(NoFocusIndicator),
    00033         paintAttributes(0),
    00034         cache(NULL)
    00035     {
    00036     }
    00037
    00038     ~PrivateData()
    00039     {
    00040         delete cache;
    00041     }
    00042
    00043     FocusIndicator focusIndicator;
    00044     int paintAttributes;
    00045     QPixmap *cache;
    00046 };
    00047
    00049
    00050 QwtPlotCanvas::QwtPlotCanvas(QwtPlot *plot):
    00051     QFrame(plot)
    00052 {
    00053     d_data = new PrivateData;
    00054
    00055 #if QT_VERSION >= 0x040100
    00056     setAutoFillBackground(true);
    00057 #endif
    00058
    00059 #if QT_VERSION < 0x040000
    00060     setWFlags(Qt::WNoAutoErase);
    00061 #ifndef QT_NO_CURSOR
    00062     setCursor(Qt::crossCursor);
    00063 #endif
    00064 #else
    00065 #ifndef QT_NO_CURSOR
    00066     setCursor(Qt::CrossCursor);
    00067 #endif
    00068 #endif // >= 0x040000
    00069
    00070     setPaintAttribute(PaintCached, true);
    00071     setPaintAttribute(PaintPacked, true);
    00072 }
    00073
    00075 QwtPlotCanvas::~QwtPlotCanvas()
    00076 {
    00077     delete d_data;
    00078 }
    00079
    00090 void QwtPlotCanvas::setPaintAttribute(PaintAttribute attribute, bool on)
    00091 {
    00092     if ( bool(d_data->paintAttributes & attribute) == on )
    00093         return;
    00094
    00095     if ( on )
    00096         d_data->paintAttributes |= attribute;
    00097     else
    00098         d_data->paintAttributes &= ~attribute;
    00099
    00100     switch(attribute)
    00101     {
    00102         case PaintCached:
    00103         {
    00104             if ( on )
    00105             {
    00106                 if ( d_data->cache == NULL )
    00107                     d_data->cache = new QPixmap();
    00108
    00109                 if ( isVisible() )
    00110                 {
    00111                     const QRect cr = contentsRect();
    00112                     *d_data->cache = QPixmap::grabWidget(this,
    00113                         cr.x(), cr.y(), cr.width(), cr.height() );
    00114                 }
    00115             }
    00116             else
    00117             {
    00118                 delete d_data->cache;
    00119                 d_data->cache = NULL;
    00120             }
    00121             break;
    00122         }
    00123         case PaintPacked:
    00124         {
    00125             /*
    00126               If not visible, changing of the background mode
    00127               is delayed until it becomes visible. This tries to avoid
    00128               looking through the canvas when the canvas is shown the first
    00129               time.
    00130              */
    00131
    00132             if ( on == false || isVisible() )
    00133                 QwtPlotCanvas::setSystemBackground(!on);
    00134
    00135             break;
    00136         }
    00137     }
    00138 }
    00139
    00146 bool QwtPlotCanvas::testPaintAttribute(PaintAttribute attribute) const
    00147 {
    00148     return (d_data->paintAttributes & attribute) != 0;
    00149 }
    00150
    00152 QPixmap *QwtPlotCanvas::paintCache()
    00153 {
    00154     return d_data->cache;
    00155 }
    00156
    00158 const QPixmap *QwtPlotCanvas::paintCache() const
    00159 {
    00160     return d_data->cache;
    00161 }
    00162
    00164 void QwtPlotCanvas::invalidatePaintCache()
    00165 {
    00166     if ( d_data->cache )
    00167         *d_data->cache = QPixmap();
    00168 }
    00169
    00175 void QwtPlotCanvas::setFocusIndicator(FocusIndicator focusIndicator)
    00176 {
    00177     d_data->focusIndicator = focusIndicator;
    00178 }
    00179
    00185 QwtPlotCanvas::FocusIndicator QwtPlotCanvas::focusIndicator() const
    00186 {
    00187     return d_data->focusIndicator;
    00188 }
    00189
    00190 void QwtPlotCanvas::hideEvent(QHideEvent *e)
    00191 {
    00192     QFrame::hideEvent(e);
    00193
    00194     if ( d_data->paintAttributes & PaintPacked )
    00195     {
    00196         // enable system background to avoid the "looking through
    00197         // the canvas" effect, for the next show
    00198
    00199         setSystemBackground(true);
    00200     }
    00201 }
    00202
    00203 void QwtPlotCanvas::paintEvent(QPaintEvent *event)
    00204 {
    00205 #if QT_VERSION >= 0x040000
    00206     QPainter painter(this);
    00207
    00208     if ( !contentsRect().contains( event->rect() ) )
    00209     {
    00210         painter.save();
    00211         painter.setClipRegion( event->region() & frameRect() );
    00212         drawFrame( &painter );
    00213         painter.restore();
    00214     }
    00215
    00216     painter.setClipRegion(event->region() & contentsRect());
    00217
    00218     drawContents( &painter );
    00219 #else // QT_VERSION < 0x040000
    00220     QFrame::paintEvent(event);
    00221 #endif
    00222
    00223     if ( d_data->paintAttributes & PaintPacked )
    00224         setSystemBackground(false);
    00225 }
    00226
    00228 void QwtPlotCanvas::drawContents(QPainter *painter)
    00229 {
    00230     if ( d_data->paintAttributes & PaintCached && d_data->cache
    00231         && d_data->cache->size() == contentsRect().size() )
    00232     {
    00233         painter->drawPixmap(contentsRect().topLeft(), *d_data->cache);
    00234     }
    00235     else
    00236     {
    00237         QwtPlot *plot = ((QwtPlot *)parent());
    00238         const bool doAutoReplot = plot->autoReplot();
    00239             plot->setAutoReplot(false);
    00240
    00241         drawCanvas(painter);
    00242
    00243         plot->setAutoReplot(doAutoReplot);
    00244     }
    00245
    00246     if ( hasFocus() && focusIndicator() == CanvasFocusIndicator )
    00247         drawFocusIndicator(painter);
    00248 }
    00249
    00259 void QwtPlotCanvas::drawCanvas(QPainter *painter)
    00260 {
    00261     if ( !contentsRect().isValid() )
    00262         return;
    00263
    00264     QBrush bgBrush;
    00265 #if QT_VERSION >= 0x040000
    00266         bgBrush = palette().brush(backgroundRole());
    00267 #else
    00268     QColorGroup::ColorRole role =
    00269         QPalette::backgroundRoleFromMode( backgroundMode() );
    00270     bgBrush = colorGroup().brush( role );
    00271 #endif
    00272
    00273     if ( d_data->paintAttributes & PaintCached && d_data->cache )
    00274     {
    00275         *d_data->cache = QPixmap(contentsRect().size());
    00276
    00277 #ifdef Q_WS_X11
    00278 #if QT_VERSION >= 0x040000
    00279         if ( d_data->cache->x11Info().screen() != x11Info().screen() )
    00280             d_data->cache->x11SetScreen(x11Info().screen());
    00281 #else
    00282         if ( d_data->cache->x11Screen() != x11Screen() )
    00283             d_data->cache->x11SetScreen(x11Screen());
    00284 #endif
    00285 #endif
    00286
    00287         if ( d_data->paintAttributes & PaintPacked )
    00288         {
    00289             QPainter bgPainter(d_data->cache);
    00290             bgPainter.setPen(Qt::NoPen);
    00291
    00292             bgPainter.setBrush(bgBrush);
    00293             bgPainter.drawRect(d_data->cache->rect());
    00294         }
    00295         else
    00296             d_data->cache->fill(this, d_data->cache->rect().topLeft());
    00297
    00298         QPainter cachePainter(d_data->cache);
    00299         cachePainter.translate(-contentsRect().x(),
    00300             -contentsRect().y());
    00301
    00302         ((QwtPlot *)parent())->drawCanvas(&cachePainter);
    00303
    00304         cachePainter.end();
    00305
    00306         painter->drawPixmap(contentsRect(), *d_data->cache);
    00307     }
    00308     else
    00309     {
    00310 #if QT_VERSION >= 0x040000
    00311         if ( d_data->paintAttributes & PaintPacked )
    00312 #endif
    00313         {
    00314             painter->save();
    00315
    00316             painter->setPen(Qt::NoPen);
    00317             painter->setBrush(bgBrush);
    00318             painter->drawRect(contentsRect());
    00319
    00320             painter->restore();
    00321         }
    00322
    00323         ((QwtPlot *)parent())->drawCanvas(painter);
    00324     }
    00325 }
    00326
    00328 void QwtPlotCanvas::drawFocusIndicator(QPainter *painter)
    00329 {
    00330     const int margin = 1;
    00331
    00332     QRect focusRect = contentsRect();
    00333     focusRect.setRect(focusRect.x() + margin, focusRect.y() + margin,
    00334         focusRect.width() - 2 * margin, focusRect.height() - 2 * margin);
    00335
    00336     QwtPainter::drawFocusRect(painter, this, focusRect);
    00337 }
    00338
    00339 void QwtPlotCanvas::setSystemBackground(bool on)
    00340 {
    00341 #if QT_VERSION < 0x040000
    00342     if ( backgroundMode() == Qt::NoBackground )
    00343     {
    00344         if ( on )
    00345             setBackgroundMode(Qt::PaletteBackground);
    00346     }
    00347     else
    00348     {
    00349         if ( !on )
    00350             setBackgroundMode(Qt::NoBackground);
    00351     }
    00352 #else
    00353     if ( testAttribute(Qt::WA_NoSystemBackground) == on )
    00354         setAttribute(Qt::WA_NoSystemBackground, !on);
    00355 #endif
    00356 }