# 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
    00081 QwtPlot *QwtPlotCanvas::plot()
    00082 {
    00083     QWidget *w = parentWidget();
    00084     if ( w && w->inherits("QwtPlot") )
    00085         return (QwtPlot *)w;
    00086
    00087     return NULL;
    00088 }
    00089
    00091 const QwtPlot *QwtPlotCanvas::plot() const
    00092 {
    00093     const QWidget *w = parentWidget();
    00094     if ( w && w->inherits("QwtPlot") )
    00095         return (QwtPlot *)w;
    00096
    00097     return NULL;
    00098 }
    00099
    00110 void QwtPlotCanvas::setPaintAttribute(PaintAttribute attribute, bool on)
    00111 {
    00112     if ( bool(d_data->paintAttributes & attribute) == on )
    00113         return;
    00114
    00115     if ( on )
    00116         d_data->paintAttributes |= attribute;
    00117     else
    00118         d_data->paintAttributes &= ~attribute;
    00119
    00120     switch(attribute)
    00121     {
    00122         case PaintCached:
    00123         {
    00124             if ( on )
    00125             {
    00126                 if ( d_data->cache == NULL )
    00127                     d_data->cache = new QPixmap();
    00128
    00129                 if ( isVisible() )
    00130                 {
    00131                     const QRect cr = contentsRect();
    00132                     *d_data->cache = QPixmap::grabWidget(this,
    00133                         cr.x(), cr.y(), cr.width(), cr.height() );
    00134                 }
    00135             }
    00136             else
    00137             {
    00138                 delete d_data->cache;
    00139                 d_data->cache = NULL;
    00140             }
    00141             break;
    00142         }
    00143         case PaintPacked:
    00144         {
    00145             /*
    00146               If not visible, changing of the background mode
    00147               is delayed until it becomes visible. This tries to avoid
    00148               looking through the canvas when the canvas is shown the first
    00149               time.
    00150              */
    00151
    00152             if ( on == false || isVisible() )
    00153                 QwtPlotCanvas::setSystemBackground(!on);
    00154
    00155             break;
    00156         }
    00157     }
    00158 }
    00159
    00167 bool QwtPlotCanvas::testPaintAttribute(PaintAttribute attribute) const
    00168 {
    00169     return (d_data->paintAttributes & attribute) != 0;
    00170 }
    00171
    00173 QPixmap *QwtPlotCanvas::paintCache()
    00174 {
    00175     return d_data->cache;
    00176 }
    00177
    00179 const QPixmap *QwtPlotCanvas::paintCache() const
    00180 {
    00181     return d_data->cache;
    00182 }
    00183
    00185 void QwtPlotCanvas::invalidatePaintCache()
    00186 {
    00187     if ( d_data->cache )
    00188         *d_data->cache = QPixmap();
    00189 }
    00190
    00196 void QwtPlotCanvas::setFocusIndicator(FocusIndicator focusIndicator)
    00197 {
    00198     d_data->focusIndicator = focusIndicator;
    00199 }
    00200
    00206 QwtPlotCanvas::FocusIndicator QwtPlotCanvas::focusIndicator() const
    00207 {
    00208     return d_data->focusIndicator;
    00209 }
    00210
    00211 void QwtPlotCanvas::hideEvent(QHideEvent *e)
    00212 {
    00213     QFrame::hideEvent(e);
    00214
    00215     if ( d_data->paintAttributes & PaintPacked )
    00216     {
    00217         // enable system background to avoid the "looking through
    00218         // the canvas" effect, for the next show
    00219
    00220         setSystemBackground(true);
    00221     }
    00222 }
    00223
    00225 void QwtPlotCanvas::paintEvent(QPaintEvent *event)
    00226 {
    00227 #if QT_VERSION >= 0x040000
    00228     QPainter painter(this);
    00229
    00230     if ( !contentsRect().contains( event->rect() ) )
    00231     {
    00232         painter.save();
    00233         painter.setClipRegion( event->region() & frameRect() );
    00234         drawFrame( &painter );
    00235         painter.restore();
    00236     }
    00237
    00238     painter.setClipRegion(event->region() & contentsRect());
    00239
    00240     drawContents( &painter );
    00241 #else // QT_VERSION < 0x040000
    00242     QFrame::paintEvent(event);
    00243 #endif
    00244
    00245     if ( d_data->paintAttributes & PaintPacked )
    00246         setSystemBackground(false);
    00247 }
    00248
    00250 void QwtPlotCanvas::drawContents(QPainter *painter)
    00251 {
    00252     if ( d_data->paintAttributes & PaintCached && d_data->cache
    00253         && d_data->cache->size() == contentsRect().size() )
    00254     {
    00255         painter->drawPixmap(contentsRect().topLeft(), *d_data->cache);
    00256     }
    00257     else
    00258     {
    00259         QwtPlot *plot = ((QwtPlot *)parent());
    00260         const bool doAutoReplot = plot->autoReplot();
    00261         plot->setAutoReplot(false);
    00262
    00263         drawCanvas(painter);
    00264
    00265         plot->setAutoReplot(doAutoReplot);
    00266     }
    00267
    00268     if ( hasFocus() && focusIndicator() == CanvasFocusIndicator )
    00269         drawFocusIndicator(painter);
    00270 }
    00271
    00281 void QwtPlotCanvas::drawCanvas(QPainter *painter)
    00282 {
    00283     if ( !contentsRect().isValid() )
    00284         return;
    00285
    00286     QBrush bgBrush;
    00287 #if QT_VERSION >= 0x040000
    00288         bgBrush = palette().brush(backgroundRole());
    00289 #else
    00290     QColorGroup::ColorRole role =
    00291         QPalette::backgroundRoleFromMode( backgroundMode() );
    00292     bgBrush = colorGroup().brush( role );
    00293 #endif
    00294
    00295     if ( d_data->paintAttributes & PaintCached && d_data->cache )
    00296     {
    00297         *d_data->cache = QPixmap(contentsRect().size());
    00298
    00299 #ifdef Q_WS_X11
    00300 #if QT_VERSION >= 0x040000
    00301         if ( d_data->cache->x11Info().screen() != x11Info().screen() )
    00302             d_data->cache->x11SetScreen(x11Info().screen());
    00303 #else
    00304         if ( d_data->cache->x11Screen() != x11Screen() )
    00305             d_data->cache->x11SetScreen(x11Screen());
    00306 #endif
    00307 #endif
    00308
    00309         if ( d_data->paintAttributes & PaintPacked )
    00310         {
    00311             QPainter bgPainter(d_data->cache);
    00312             bgPainter.setPen(Qt::NoPen);
    00313
    00314             bgPainter.setBrush(bgBrush);
    00315             bgPainter.drawRect(d_data->cache->rect());
    00316         }
    00317         else
    00318             d_data->cache->fill(this, d_data->cache->rect().topLeft());
    00319
    00320         QPainter cachePainter(d_data->cache);
    00321         cachePainter.translate(-contentsRect().x(),
    00322             -contentsRect().y());
    00323
    00324         ((QwtPlot *)parent())->drawCanvas(&cachePainter);
    00325
    00326         cachePainter.end();
    00327
    00328         painter->drawPixmap(contentsRect(), *d_data->cache);
    00329     }
    00330     else
    00331     {
    00332 #if QT_VERSION >= 0x040000
    00333         if ( d_data->paintAttributes & PaintPacked )
    00334 #endif
    00335         {
    00336             painter->save();
    00337
    00338             painter->setPen(Qt::NoPen);
    00339             painter->setBrush(bgBrush);
    00340             painter->drawRect(contentsRect());
    00341
    00342             painter->restore();
    00343         }
    00344
    00345         ((QwtPlot *)parent())->drawCanvas(painter);
    00346     }
    00347 }
    00348
    00350 void QwtPlotCanvas::drawFocusIndicator(QPainter *painter)
    00351 {
    00352     const int margin = 1;
    00353
    00354     QRect focusRect = contentsRect();
    00355     focusRect.setRect(focusRect.x() + margin, focusRect.y() + margin,
    00356         focusRect.width() - 2 * margin, focusRect.height() - 2 * margin);
    00357
    00358     QwtPainter::drawFocusRect(painter, this, focusRect);
    00359 }
    00360
    00361 void QwtPlotCanvas::setSystemBackground(bool on)
    00362 {
    00363 #if QT_VERSION < 0x040000
    00364     if ( backgroundMode() == Qt::NoBackground )
    00365     {
    00366         if ( on )
    00367             setBackgroundMode(Qt::PaletteBackground);
    00368     }
    00369     else
    00370     {
    00371         if ( !on )
    00372             setBackgroundMode(Qt::NoBackground);
    00373     }
    00374 #else
    00375     if ( testAttribute(Qt::WA_NoSystemBackground) == on )
    00376         setAttribute(Qt::WA_NoSystemBackground, !on);
    00377 #endif
    00378 }