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

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 #include <qevent.h>
00015 #include "qwt_painter.h"
00016 #include "qwt_math.h"
00017 #include "qwt_plot.h"
00018 #include "qwt_paint_buffer.h"
00019 #include "qwt_plot_canvas.h"
00020 
00021 static const int dim = 5000;
00022 
00024 
00025 QwtPlotCanvas::QwtPlotCanvas(QwtPlot *plot):
00026     QFrame(plot, "canvas", Qt::WRepaintNoErase|Qt::WResizeNoErase),
00027     d_focusIndicator(CanvasFocusIndicator),
00028     d_cacheMode(TRUE),
00029     d_cache(NULL)
00030 #ifndef QWT_NO_COMPAT
00031     ,d_outlineEnabled(FALSE),
00032     d_outlineActive(FALSE),
00033     d_mousePressed(FALSE),
00034     d_outline(Qwt::Rect),
00035     d_pen(Qt::red)
00036 #endif
00037 {
00038     setCursor(Qt::crossCursor);
00039 }
00040 
00042 QwtPlotCanvas::~QwtPlotCanvas()
00043 {
00044     delete d_cache;
00045 }
00046 
00066 void QwtPlotCanvas::setCacheMode(bool on)
00067 {
00068     if ( d_cacheMode != on )
00069     {
00070         d_cacheMode = on;
00071         if (!d_cacheMode )
00072         {
00073             delete d_cache;
00074             d_cache = NULL;
00075         }
00076     }
00077 }
00078 
00083 bool QwtPlotCanvas::cacheMode() const
00084 {
00085     return d_cacheMode;
00086 }
00087 
00089 QPixmap *QwtPlotCanvas::cache()
00090 {
00091     return d_cache;
00092 }
00093 
00095 const QPixmap *QwtPlotCanvas::cache() const
00096 {
00097     return d_cache;
00098 }
00099 
00101 void QwtPlotCanvas::invalidateCache()
00102 {
00103     if ( d_cache )
00104         d_cache->resize(0, 0);
00105 }
00106 
00112 void QwtPlotCanvas::setFocusIndicator(FocusIndicator focusIndicator)
00113 {
00114     d_focusIndicator = focusIndicator;
00115 }
00116 
00122 QwtPlotCanvas::FocusIndicator QwtPlotCanvas::focusIndicator() const
00123 {
00124     return d_focusIndicator;
00125 }
00126 
00128 void QwtPlotCanvas::frameChanged()
00129 {
00130     QFrame::frameChanged();
00131 
00132     // frame changes change the size of the contents rect, what
00133     // is related to the axes. So we have to update the layout.
00134 
00135     ((QwtPlot *)parent())->updateLayout();
00136 }
00137 
00139 void QwtPlotCanvas::drawContents(QPainter *painter)
00140 {
00141     if ( cacheMode() && d_cache 
00142         && d_cache->size() == contentsRect().size() )
00143     {
00144         painter->drawPixmap(contentsRect().topLeft(), *d_cache);
00145     }
00146     else
00147         drawCanvas(painter);
00148 
00149 #ifndef QWT_NO_COMPAT
00150     if ( d_outlineActive )
00151         drawOutline(*painter); // redraw outline
00152 #endif
00153 
00154     if ( hasFocus() && focusIndicator() == CanvasFocusIndicator )
00155     {
00156         const int margin = 1;
00157         QRect focusRect = contentsRect();
00158         focusRect.setRect(focusRect.x() + margin, focusRect.y() + margin,
00159             focusRect.width() - 2 * margin, focusRect.height() - 2 * margin);
00160 
00161         drawFocusIndicator(painter, focusRect);
00162     }
00163 }
00164 
00174 void QwtPlotCanvas::drawCanvas(QPainter *painter)
00175 {
00176     if ( !contentsRect().isValid() )
00177         return;
00178 
00179     QRect clipRect = contentsRect();
00180     if ( !cacheMode() || !QwtPaintBuffer::isEnabled() )
00181     {
00182         // If we donīt need the paint buffer as cache we can
00183         // use the clip for painting to the buffer too. 
00184 
00185         if ( painter && !painter->clipRegion().isNull() )
00186             clipRect = painter->clipRegion().boundingRect();
00187     }
00188 
00189     QwtPaintBuffer paintBuffer(this, clipRect, painter);
00190     ((QwtPlot *)parent())->drawCanvas(paintBuffer.painter());
00191 
00192     if ( cacheMode() )
00193     {
00194         if ( d_cache == NULL )
00195             d_cache = new QPixmap(contentsRect().size());
00196         else
00197             d_cache->resize(contentsRect().size());
00198 
00199         if ( QwtPaintBuffer::isEnabled() )
00200             *d_cache = paintBuffer.buffer();
00201         else
00202         {
00203             d_cache->fill(this, 0, 0);
00204             QPainter cachePainter(d_cache);
00205             cachePainter.translate(-contentsRect().x(),
00206                 -contentsRect().y());
00207             ((QwtPlot *)parent())->drawCanvas(&cachePainter);
00208         }
00209     }
00210 }
00211 
00213 void QwtPlotCanvas::drawFocusIndicator(QPainter *painter, const QRect &rect)
00214 {
00215 #if QT_VERSION < 300
00216         style().drawFocusRect(painter, rect, colorGroup());
00217 #else
00218         style().drawPrimitive(QStyle::PE_FocusRect, painter,
00219             rect, colorGroup());
00220 #endif
00221 }
00222 
00223 #ifndef QWT_NO_COMPAT
00224 
00226 void QwtPlotCanvas::mousePressEvent(QMouseEvent *e)
00227 {
00228     if (d_outlineActive)
00229     {
00230         QPainter p(this);
00231         drawOutline(p); // Delete active outlines
00232     }
00233 
00234     d_outlineActive = FALSE;
00235 
00236     //
00237     // store this point as entry point
00238     //
00239     d_lastPoint = e->pos();
00240     d_entryPoint = e->pos();
00241 
00242     if (d_outlineEnabled)
00243     {
00244         QPainter p(this);
00245         drawOutline(p); // draw new outline
00246         d_outlineActive = TRUE;
00247     }
00248 
00249     d_mousePressed = TRUE;
00250 
00251     QMouseEvent m(QEvent::MouseButtonPress, 
00252         e->pos() - rect().topLeft(), e->button(), e->state());
00253 
00254     emit mousePressed(m);
00255 }
00256 
00258 void QwtPlotCanvas::mouseReleaseEvent(QMouseEvent *e)
00259 {
00260     if (d_outlineActive)
00261     {
00262         QPainter p(this);
00263         drawOutline(p);
00264     }
00265 
00266     d_outlineActive = FALSE;
00267     d_mousePressed = FALSE;
00268 
00269     QMouseEvent m(QEvent::MouseButtonRelease, 
00270         e->pos() - rect().topLeft(), e->button(), e->state());
00271 
00272     emit mouseReleased(m);
00273 }
00274 
00276 void QwtPlotCanvas::mouseMoveEvent(QMouseEvent *e)
00277 {
00278     if (d_outlineActive)
00279     {
00280         QPainter p(this);
00281         drawOutline(p);
00282         d_lastPoint = e->pos();
00283         drawOutline(p);
00284     }
00285 
00286     QMouseEvent m(QEvent::MouseMove, 
00287         e->pos() - rect().topLeft(), e->button(), e->state());
00288 
00289     emit mouseMoved(m);
00290 }
00291 
00307 void QwtPlotCanvas::enableOutline(bool tf)
00308 {
00309 
00310     //
00311     //  If the mouse is pressed, erase existing outline
00312     //  or draw new outline if 'tf' changes the 'enabled' state.
00313     //
00314     if ((tf != d_outlineEnabled) && d_mousePressed)
00315     {
00316         QPainter p(this);
00317         drawOutline(p);
00318         d_outlineActive = tf;
00319     }
00320     d_outlineEnabled = tf;
00321 }
00322 
00332 bool QwtPlotCanvas::outlineEnabled() const 
00333 { 
00334     return d_outlineEnabled; 
00335 }
00336 
00371 void QwtPlotCanvas::setOutlineStyle(Qwt::Shape os)
00372 {
00373     if (d_outlineActive)
00374     {
00375         QPainter p(this); // erase old outline
00376         drawOutline(p);
00377     }
00378 
00379     d_outline = os;
00380 
00381     if (d_outlineActive)
00382     {
00383         QPainter p(this);
00384         drawOutline(p); // draw new outline
00385     }
00386 }
00387 
00396 Qwt::Shape QwtPlotCanvas::outlineStyle() const 
00397 { 
00398     return d_outline; 
00399 }
00400 
00411 void QwtPlotCanvas::setOutlinePen(const QPen &pen)
00412 {
00413     d_pen = pen;
00414 }
00415 
00425 const QPen& QwtPlotCanvas::outlinePen() const 
00426 { 
00427     return d_pen; 
00428 }
00429 
00436 void QwtPlotCanvas::drawOutline(QPainter &p)
00437 {
00438     const QRect &r = contentsRect();
00439 
00440     QColor bg = ((QwtPlot *)parent())->canvasBackground();
00441 
00442     QPen pn = d_pen;
00443     pn.setColor(QColor(bg.rgb() ^ d_pen.color().rgb()));
00444 
00445     p.setPen(pn);
00446     p.setRasterOp(XorROP);
00447     p.setClipRect(r);
00448     p.setClipping(TRUE);
00449 
00450     switch(d_outline)
00451     {
00452         case Qwt::VLine:
00453             QwtPainter::drawLine(&p, d_lastPoint.x(), 
00454                 r.top(), d_lastPoint.x(), r.bottom());
00455             break;
00456         
00457         case Qwt::HLine:
00458             QwtPainter::drawLine(&p, r.left(), 
00459                 d_lastPoint.y(), r.right(), d_lastPoint.y());
00460             break;
00461         
00462         case Qwt::Cross:
00463             QwtPainter::drawLine(&p, r.left(), 
00464                 d_lastPoint.y(), r.right(), d_lastPoint.y());
00465             QwtPainter::drawLine(&p, d_lastPoint.x(), 
00466                 r.top(), d_lastPoint.x(), r.bottom());
00467             break;
00468 
00469         case Qwt::Rect:
00470             QwtPainter::drawRect(&p, d_entryPoint.x(), d_entryPoint.y(),
00471                d_lastPoint.x() - d_entryPoint.x() + 1,
00472                d_lastPoint.y() - d_entryPoint.y() + 1);
00473             break;
00474         
00475         case Qwt::Ellipse:
00476             p.drawEllipse(d_entryPoint.x(), d_entryPoint.y(),
00477                d_lastPoint.x() - d_entryPoint.x() + 1,
00478                d_lastPoint.y() - d_entryPoint.y() + 1);
00479             break;
00480 
00481         default:
00482             break;
00483     }
00484 }
00485 
00486 #endif // !QWT_NO_COMPAT
00487 
00488 // Local Variables:
00489 // mode: C++
00490 // c-file-style: "stroustrup"
00491 // indent-tabs-mode: nil
00492 // End:
00493 

Generated on Sun Sep 26 23:24:37 2004 for Qwt User's Guide by doxygen 1.3.6