qwt_plot_canvas.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
  2. * Qwt Widget Library
  3. * Copyright (C) 1997 Josef Wilgen
  4. * Copyright (C) 2002 Uwe Rathmann
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the Qwt License, Version 1.0
  8. *****************************************************************************/
  9. #include "qwt_plot_canvas.h"
  10. #include "qwt_painter.h"
  11. #include "qwt_math.h"
  12. #include "qwt_plot.h"
  13. #include <qpainter.h>
  14. #include <qstyle.h>
  15. #include <qstyleoption.h>
  16. #include <qpaintengine.h>
  17. #ifdef Q_WS_X11
  18. #include <qx11info_x11.h>
  19. #endif
  20. #include <qevent.h>
  21. class QwtPlotCanvas::PrivateData
  22. {
  23. public:
  24. PrivateData():
  25. focusIndicator( NoFocusIndicator ),
  26. paintAttributes( 0 ),
  27. cache( NULL )
  28. {
  29. }
  30. ~PrivateData()
  31. {
  32. delete cache;
  33. }
  34. FocusIndicator focusIndicator;
  35. int paintAttributes;
  36. QPixmap *cache;
  37. };
  38. //! Sets a cross cursor, enables QwtPlotCanvas::PaintCached
  39. QwtPlotCanvas::QwtPlotCanvas( QwtPlot *plot ):
  40. QFrame( plot )
  41. {
  42. d_data = new PrivateData;
  43. setAutoFillBackground( true );
  44. #ifndef QT_NO_CURSOR
  45. setCursor( Qt::CrossCursor );
  46. #endif
  47. setPaintAttribute( PaintCached, true );
  48. setPaintAttribute( PaintPacked, true );
  49. }
  50. //! Destructor
  51. QwtPlotCanvas::~QwtPlotCanvas()
  52. {
  53. delete d_data;
  54. }
  55. //! Return parent plot widget
  56. QwtPlot *QwtPlotCanvas::plot()
  57. {
  58. return qobject_cast<QwtPlot *>( parentWidget() );
  59. }
  60. //! Return parent plot widget
  61. const QwtPlot *QwtPlotCanvas::plot() const
  62. {
  63. return qobject_cast<const QwtPlot *>( parentWidget() );
  64. }
  65. /*!
  66. \brief Changing the paint attributes
  67. \param attribute Paint attribute
  68. \param on On/Off
  69. The default setting enables PaintCached and PaintPacked
  70. \sa testPaintAttribute(), drawCanvas(), drawContents(), paintCache()
  71. */
  72. void QwtPlotCanvas::setPaintAttribute( PaintAttribute attribute, bool on )
  73. {
  74. if ( bool( d_data->paintAttributes & attribute ) == on )
  75. return;
  76. if ( on )
  77. d_data->paintAttributes |= attribute;
  78. else
  79. d_data->paintAttributes &= ~attribute;
  80. switch ( attribute )
  81. {
  82. case PaintCached:
  83. {
  84. if ( on )
  85. {
  86. if ( d_data->cache == NULL )
  87. d_data->cache = new QPixmap();
  88. if ( isVisible() )
  89. {
  90. const QRect cr = contentsRect();
  91. *d_data->cache = QPixmap::grabWidget( this,
  92. cr.x(), cr.y(), cr.width(), cr.height() );
  93. }
  94. }
  95. else
  96. {
  97. delete d_data->cache;
  98. d_data->cache = NULL;
  99. }
  100. break;
  101. }
  102. case PaintPacked:
  103. {
  104. /*
  105. If not visible, changing of the background mode
  106. is delayed until it becomes visible. This tries to avoid
  107. looking through the canvas when the canvas is shown the first
  108. time.
  109. */
  110. if ( on == false || isVisible() )
  111. QwtPlotCanvas::setSystemBackground( !on );
  112. break;
  113. }
  114. }
  115. }
  116. /*!
  117. Test wether a paint attribute is enabled
  118. \param attribute Paint attribute
  119. \return true if the attribute is enabled
  120. \sa setPaintAttribute()
  121. */
  122. bool QwtPlotCanvas::testPaintAttribute( PaintAttribute attribute ) const
  123. {
  124. return ( d_data->paintAttributes & attribute ) != 0;
  125. }
  126. //! Return the paint cache, might be null
  127. QPixmap *QwtPlotCanvas::paintCache()
  128. {
  129. return d_data->cache;
  130. }
  131. //! Return the paint cache, might be null
  132. const QPixmap *QwtPlotCanvas::paintCache() const
  133. {
  134. return d_data->cache;
  135. }
  136. //! Invalidate the internal paint cache
  137. void QwtPlotCanvas::invalidatePaintCache()
  138. {
  139. if ( d_data->cache )
  140. *d_data->cache = QPixmap();
  141. }
  142. /*!
  143. Set the focus indicator
  144. \sa FocusIndicator, focusIndicator()
  145. */
  146. void QwtPlotCanvas::setFocusIndicator( FocusIndicator focusIndicator )
  147. {
  148. d_data->focusIndicator = focusIndicator;
  149. }
  150. /*!
  151. \return Focus indicator
  152. \sa FocusIndicator, setFocusIndicator()
  153. */
  154. QwtPlotCanvas::FocusIndicator QwtPlotCanvas::focusIndicator() const
  155. {
  156. return d_data->focusIndicator;
  157. }
  158. /*!
  159. Hide event
  160. \param event Hide event
  161. */
  162. void QwtPlotCanvas::hideEvent( QHideEvent *event )
  163. {
  164. QFrame::hideEvent( event );
  165. if ( d_data->paintAttributes & PaintPacked )
  166. {
  167. // enable system background to avoid the "looking through
  168. // the canvas" effect, for the next show
  169. setSystemBackground( true );
  170. }
  171. }
  172. /*!
  173. Paint event
  174. \param event Paint event
  175. */
  176. void QwtPlotCanvas::paintEvent( QPaintEvent *event )
  177. {
  178. QPainter painter( this );
  179. if ( !contentsRect().contains( event->rect() ) )
  180. {
  181. painter.save();
  182. painter.setClipRegion( event->region() & frameRect() );
  183. drawFrame( &painter );
  184. painter.restore();
  185. }
  186. painter.setClipRegion( event->region() & contentsRect() );
  187. drawContents( &painter );
  188. if ( d_data->paintAttributes & PaintPacked )
  189. setSystemBackground( false );
  190. }
  191. /*!
  192. Redraw the canvas, and focus rect
  193. \param painter Painter
  194. */
  195. void QwtPlotCanvas::drawContents( QPainter *painter )
  196. {
  197. if ( d_data->paintAttributes & PaintCached && d_data->cache
  198. && d_data->cache->size() == contentsRect().size() )
  199. {
  200. painter->drawPixmap( contentsRect().topLeft(), *d_data->cache );
  201. }
  202. else
  203. {
  204. QwtPlot *plot = ( ( QwtPlot * )parent() );
  205. const bool doAutoReplot = plot->autoReplot();
  206. plot->setAutoReplot( false );
  207. drawCanvas( painter );
  208. plot->setAutoReplot( doAutoReplot );
  209. }
  210. if ( hasFocus() && focusIndicator() == CanvasFocusIndicator )
  211. drawFocusIndicator( painter );
  212. }
  213. /*!
  214. Draw the the canvas
  215. Paints all plot items to the contentsRect(), using QwtPlot::drawCanvas
  216. and updates the paint cache.
  217. \param painter Painter
  218. \sa QwtPlot::drawCanvas(), setPaintAttributes(), testPaintAttributes()
  219. */
  220. void QwtPlotCanvas::drawCanvas( QPainter *painter )
  221. {
  222. if ( !contentsRect().isValid() )
  223. return;
  224. QBrush bgBrush = palette().brush( backgroundRole() );
  225. if ( d_data->paintAttributes & PaintCached && d_data->cache )
  226. {
  227. *d_data->cache = QPixmap( contentsRect().size() );
  228. #ifdef Q_WS_X11
  229. if ( d_data->cache->x11Info().screen() != x11Info().screen() )
  230. d_data->cache->x11SetScreen( x11Info().screen() );
  231. #endif
  232. if ( d_data->paintAttributes & PaintPacked )
  233. {
  234. QPainter bgPainter( d_data->cache );
  235. bgPainter.setPen( Qt::NoPen );
  236. bgPainter.setBrush( bgBrush );
  237. bgPainter.drawRect( d_data->cache->rect() );
  238. }
  239. else
  240. d_data->cache->fill( this, d_data->cache->rect().topLeft() );
  241. QPainter cachePainter( d_data->cache );
  242. cachePainter.translate( -contentsRect().x(),
  243. -contentsRect().y() );
  244. ( ( QwtPlot * )parent() )->drawCanvas( &cachePainter );
  245. cachePainter.end();
  246. painter->drawPixmap( contentsRect(), *d_data->cache );
  247. }
  248. else
  249. {
  250. if ( d_data->paintAttributes & PaintPacked )
  251. {
  252. painter->save();
  253. painter->setPen( Qt::NoPen );
  254. painter->setBrush( bgBrush );
  255. painter->drawRect( contentsRect() );
  256. painter->restore();
  257. }
  258. ( ( QwtPlot * )parent() )->drawCanvas( painter );
  259. }
  260. }
  261. /*!
  262. Draw the focus indication
  263. \param painter Painter
  264. */
  265. void QwtPlotCanvas::drawFocusIndicator( QPainter *painter )
  266. {
  267. const int margin = 1;
  268. QRect focusRect = contentsRect();
  269. focusRect.setRect( focusRect.x() + margin, focusRect.y() + margin,
  270. focusRect.width() - 2 * margin, focusRect.height() - 2 * margin );
  271. QwtPainter::drawFocusRect( painter, this, focusRect );
  272. }
  273. void QwtPlotCanvas::setSystemBackground( bool on )
  274. {
  275. if ( testAttribute( Qt::WA_NoSystemBackground ) == on )
  276. setAttribute( Qt::WA_NoSystemBackground, !on );
  277. }
  278. /*!
  279. Invalidate the paint cache and repaint the canvas
  280. \sa invalidatePaintCache()
  281. */
  282. void QwtPlotCanvas::replot()
  283. {
  284. invalidatePaintCache();
  285. /*
  286. In case of cached or packed painting the canvas
  287. is repainted completely and doesn't need to be erased.
  288. */
  289. const bool erase =
  290. !testPaintAttribute( QwtPlotCanvas::PaintPacked )
  291. && !testPaintAttribute( QwtPlotCanvas::PaintCached );
  292. const bool noBackgroundMode = testAttribute( Qt::WA_NoBackground );
  293. if ( !erase && !noBackgroundMode )
  294. setAttribute( Qt::WA_NoBackground, true );
  295. repaint( contentsRect() );
  296. if ( !erase && !noBackgroundMode )
  297. setAttribute( Qt::WA_NoBackground, false );
  298. }