/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** * Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ // vim: expandtab #include #include #if QT_VERSION >= 0x040000 #include #include #ifdef Q_WS_X11 #include #endif #endif #include #include "qwt_painter.h" #include "qwt_math.h" #include "qwt_plot.h" #include "qwt_paint_buffer.h" #include "qwt_plot_canvas.h" class QwtPlotCanvas::PrivateData { public: PrivateData(): focusIndicator(NoFocusIndicator), paintAttributes(0), cache(NULL) { } ~PrivateData() { delete cache; } FocusIndicator focusIndicator; int paintAttributes; QPixmap *cache; }; //! Sets a cross cursor, enables QwtPlotCanvas::PaintCached QwtPlotCanvas::QwtPlotCanvas(QwtPlot *plot): QFrame(plot) { d_data = new PrivateData; #if QT_VERSION >= 0x040100 setAutoFillBackground(true); #endif #if QT_VERSION < 0x040000 setWFlags(Qt::WNoAutoErase); #ifndef QT_NO_CURSOR setCursor(Qt::crossCursor); #endif #else #ifndef QT_NO_CURSOR setCursor(Qt::CrossCursor); #endif #endif // >= 0x040000 setPaintAttribute(PaintCached, true); setPaintAttribute(PaintPacked, true); } //! Destructor QwtPlotCanvas::~QwtPlotCanvas() { delete d_data; } //! Return parent plot widget QwtPlot *QwtPlotCanvas::plot() { QWidget *w = parentWidget(); if ( w && w->inherits("QwtPlot") ) return (QwtPlot *)w; return NULL; } //! Return parent plot widget const QwtPlot *QwtPlotCanvas::plot() const { const QWidget *w = parentWidget(); if ( w && w->inherits("QwtPlot") ) return (QwtPlot *)w; return NULL; } /*! \brief Changing the paint attributes \param attribute Paint attribute \param on On/Off The default setting enables PaintCached and PaintPacked \sa testPaintAttribute(), drawCanvas(), drawContents(), paintCache() */ void QwtPlotCanvas::setPaintAttribute(PaintAttribute attribute, bool on) { if ( bool(d_data->paintAttributes & attribute) == on ) return; if ( on ) d_data->paintAttributes |= attribute; else d_data->paintAttributes &= ~attribute; switch(attribute) { case PaintCached: { if ( on ) { if ( d_data->cache == NULL ) d_data->cache = new QPixmap(); if ( isVisible() ) { const QRect cr = contentsRect(); *d_data->cache = QPixmap::grabWidget(this, cr.x(), cr.y(), cr.width(), cr.height() ); } } else { delete d_data->cache; d_data->cache = NULL; } break; } case PaintPacked: { /* If not visible, changing of the background mode is delayed until it becomes visible. This tries to avoid looking through the canvas when the canvas is shown the first time. */ if ( on == false || isVisible() ) QwtPlotCanvas::setSystemBackground(!on); break; } } } /*! Test wether a paint attribute is enabled \param attribute Paint attribute \return true if the attribute is enabled \sa setPaintAttribute() */ bool QwtPlotCanvas::testPaintAttribute(PaintAttribute attribute) const { return (d_data->paintAttributes & attribute) != 0; } //! Return the paint cache, might be null QPixmap *QwtPlotCanvas::paintCache() { return d_data->cache; } //! Return the paint cache, might be null const QPixmap *QwtPlotCanvas::paintCache() const { return d_data->cache; } //! Invalidate the internal paint cache void QwtPlotCanvas::invalidatePaintCache() { if ( d_data->cache ) *d_data->cache = QPixmap(); } /*! Set the focus indicator \sa FocusIndicator, focusIndicator */ void QwtPlotCanvas::setFocusIndicator(FocusIndicator focusIndicator) { d_data->focusIndicator = focusIndicator; } /*! \return Focus indicator \sa FocusIndicator, setFocusIndicator */ QwtPlotCanvas::FocusIndicator QwtPlotCanvas::focusIndicator() const { return d_data->focusIndicator; } void QwtPlotCanvas::hideEvent(QHideEvent *e) { QFrame::hideEvent(e); if ( d_data->paintAttributes & PaintPacked ) { // enable system background to avoid the "looking through // the canvas" effect, for the next show setSystemBackground(true); } } //! Paint event void QwtPlotCanvas::paintEvent(QPaintEvent *event) { #if QT_VERSION >= 0x040000 QPainter painter(this); if ( !contentsRect().contains( event->rect() ) ) { painter.save(); painter.setClipRegion( event->region() & frameRect() ); drawFrame( &painter ); painter.restore(); } painter.setClipRegion(event->region() & contentsRect()); drawContents( &painter ); #else // QT_VERSION < 0x040000 QFrame::paintEvent(event); #endif if ( d_data->paintAttributes & PaintPacked ) setSystemBackground(false); } //! Redraw the canvas, and focus rect void QwtPlotCanvas::drawContents(QPainter *painter) { if ( d_data->paintAttributes & PaintCached && d_data->cache && d_data->cache->size() == contentsRect().size() ) { painter->drawPixmap(contentsRect().topLeft(), *d_data->cache); } else { QwtPlot *plot = ((QwtPlot *)parent()); const bool doAutoReplot = plot->autoReplot(); plot->setAutoReplot(false); drawCanvas(painter); plot->setAutoReplot(doAutoReplot); } if ( hasFocus() && focusIndicator() == CanvasFocusIndicator ) drawFocusIndicator(painter); } /*! Draw the the canvas Paints all plot items to the contentsRect(), using QwtPlot::drawCanvas and updates the paint cache. \sa QwtPlot::drawCanvas, setPaintAttributes(), testPaintAttributes() */ void QwtPlotCanvas::drawCanvas(QPainter *painter) { if ( !contentsRect().isValid() ) return; QBrush bgBrush; #if QT_VERSION >= 0x040000 bgBrush = palette().brush(backgroundRole()); #else QColorGroup::ColorRole role = QPalette::backgroundRoleFromMode( backgroundMode() ); bgBrush = colorGroup().brush( role ); #endif if ( d_data->paintAttributes & PaintCached && d_data->cache ) { *d_data->cache = QPixmap(contentsRect().size()); #ifdef Q_WS_X11 #if QT_VERSION >= 0x040000 if ( d_data->cache->x11Info().screen() != x11Info().screen() ) d_data->cache->x11SetScreen(x11Info().screen()); #else if ( d_data->cache->x11Screen() != x11Screen() ) d_data->cache->x11SetScreen(x11Screen()); #endif #endif if ( d_data->paintAttributes & PaintPacked ) { QPainter bgPainter(d_data->cache); bgPainter.setPen(Qt::NoPen); bgPainter.setBrush(bgBrush); bgPainter.drawRect(d_data->cache->rect()); } else d_data->cache->fill(this, d_data->cache->rect().topLeft()); QPainter cachePainter(d_data->cache); cachePainter.translate(-contentsRect().x(), -contentsRect().y()); ((QwtPlot *)parent())->drawCanvas(&cachePainter); cachePainter.end(); painter->drawPixmap(contentsRect(), *d_data->cache); } else { #if QT_VERSION >= 0x040000 if ( d_data->paintAttributes & PaintPacked ) #endif { painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(bgBrush); painter->drawRect(contentsRect()); painter->restore(); } ((QwtPlot *)parent())->drawCanvas(painter); } } //! Draw the focus indication void QwtPlotCanvas::drawFocusIndicator(QPainter *painter) { const int margin = 1; QRect focusRect = contentsRect(); focusRect.setRect(focusRect.x() + margin, focusRect.y() + margin, focusRect.width() - 2 * margin, focusRect.height() - 2 * margin); QwtPainter::drawFocusRect(painter, this, focusRect); } void QwtPlotCanvas::setSystemBackground(bool on) { #if QT_VERSION < 0x040000 if ( backgroundMode() == Qt::NoBackground ) { if ( on ) setBackgroundMode(Qt::PaletteBackground); } else { if ( !on ) setBackgroundMode(Qt::NoBackground); } #else if ( testAttribute(Qt::WA_NoSystemBackground) == on ) setAttribute(Qt::WA_NoSystemBackground, !on); #endif }