qwt_plot_item.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  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_item.h"
  10. #include "qwt_text.h"
  11. #include "qwt_plot.h"
  12. #include "qwt_legend.h"
  13. #include "qwt_legend_item.h"
  14. #include <qpainter.h>
  15. class QwtPlotItem::PrivateData
  16. {
  17. public:
  18. PrivateData():
  19. plot( NULL ),
  20. isVisible( true ),
  21. attributes( 0 ),
  22. renderHints( 0 ),
  23. z( 0.0 ),
  24. xAxis( QwtPlot::xBottom ),
  25. yAxis( QwtPlot::yLeft )
  26. {
  27. }
  28. mutable QwtPlot *plot;
  29. bool isVisible;
  30. int attributes;
  31. int renderHints;
  32. double z;
  33. int xAxis;
  34. int yAxis;
  35. QwtText title;
  36. };
  37. /*!
  38. Constructor
  39. \param title Title of the item
  40. */
  41. QwtPlotItem::QwtPlotItem( const QwtText &title )
  42. {
  43. d_data = new PrivateData;
  44. d_data->title = title;
  45. }
  46. //! Destroy the QwtPlotItem
  47. QwtPlotItem::~QwtPlotItem()
  48. {
  49. attach( NULL );
  50. delete d_data;
  51. }
  52. /*!
  53. \brief Attach the item to a plot.
  54. This method will attach a QwtPlotItem to the QwtPlot argument. It will first
  55. detach the QwtPlotItem from any plot from a previous call to attach (if
  56. necessary). If a NULL argument is passed, it will detach from any QwtPlot it
  57. was attached to.
  58. \param plot Plot widget
  59. \sa detach()
  60. */
  61. void QwtPlotItem::attach( QwtPlot *plot )
  62. {
  63. if ( plot == d_data->plot )
  64. return;
  65. // remove the item from the previous plot
  66. if ( d_data->plot )
  67. {
  68. if ( d_data->plot->legend() )
  69. d_data->plot->legend()->remove( this );
  70. d_data->plot->attachItem( this, false );
  71. if ( d_data->plot->autoReplot() )
  72. d_data->plot->update();
  73. }
  74. d_data->plot = plot;
  75. if ( d_data->plot )
  76. {
  77. // insert the item into the current plot
  78. d_data->plot->attachItem( this, true );
  79. itemChanged();
  80. }
  81. }
  82. /*!
  83. Return rtti for the specific class represented. QwtPlotItem is simply
  84. a virtual interface class, and base classes will implement this method
  85. with specific rtti values so a user can differentiate them.
  86. The rtti value is useful for environments, where the
  87. runtime type information is disabled and it is not possible
  88. to do a dynamic_cast<...>.
  89. \return rtti value
  90. \sa RttiValues
  91. */
  92. int QwtPlotItem::rtti() const
  93. {
  94. return Rtti_PlotItem;
  95. }
  96. //! Return attached plot
  97. QwtPlot *QwtPlotItem::plot() const
  98. {
  99. return d_data->plot;
  100. }
  101. /*!
  102. Plot items are painted in increasing z-order.
  103. \return setZ(), QwtPlotDict::itemList()
  104. */
  105. double QwtPlotItem::z() const
  106. {
  107. return d_data->z;
  108. }
  109. /*!
  110. \brief Set the z value
  111. Plot items are painted in increasing z-order.
  112. \param z Z-value
  113. \sa z(), QwtPlotDict::itemList()
  114. */
  115. void QwtPlotItem::setZ( double z )
  116. {
  117. if ( d_data->z != z )
  118. {
  119. d_data->z = z;
  120. if ( d_data->plot )
  121. {
  122. // update the z order
  123. d_data->plot->attachItem( this, false );
  124. d_data->plot->attachItem( this, true );
  125. }
  126. itemChanged();
  127. }
  128. }
  129. /*!
  130. Set a new title
  131. \param title Title
  132. \sa title()
  133. */
  134. void QwtPlotItem::setTitle( const QString &title )
  135. {
  136. setTitle( QwtText( title ) );
  137. }
  138. /*!
  139. Set a new title
  140. \param title Title
  141. \sa title()
  142. */
  143. void QwtPlotItem::setTitle( const QwtText &title )
  144. {
  145. if ( d_data->title != title )
  146. {
  147. d_data->title = title;
  148. itemChanged();
  149. }
  150. }
  151. /*!
  152. \return Title of the item
  153. \sa setTitle()
  154. */
  155. const QwtText &QwtPlotItem::title() const
  156. {
  157. return d_data->title;
  158. }
  159. /*!
  160. Toggle an item attribute
  161. \param attribute Attribute type
  162. \param on true/false
  163. \sa testItemAttribute(), ItemAttribute
  164. */
  165. void QwtPlotItem::setItemAttribute( ItemAttribute attribute, bool on )
  166. {
  167. if ( bool( d_data->attributes & attribute ) != on )
  168. {
  169. if ( on )
  170. d_data->attributes |= attribute;
  171. else
  172. d_data->attributes &= ~attribute;
  173. itemChanged();
  174. }
  175. }
  176. /*!
  177. Test an item attribute
  178. \param attribute Attribute type
  179. \return true/false
  180. \sa setItemAttribute(), ItemAttribute
  181. */
  182. bool QwtPlotItem::testItemAttribute( ItemAttribute attribute ) const
  183. {
  184. return d_data->attributes & attribute;
  185. }
  186. /*!
  187. Toggle an render hint
  188. \param hint Render hint
  189. \param on true/false
  190. \sa testRenderHint(), RenderHint
  191. */
  192. void QwtPlotItem::setRenderHint( RenderHint hint, bool on )
  193. {
  194. if ( ( ( d_data->renderHints & hint ) != 0 ) != on )
  195. {
  196. if ( on )
  197. d_data->renderHints |= hint;
  198. else
  199. d_data->renderHints &= ~hint;
  200. itemChanged();
  201. }
  202. }
  203. /*!
  204. Test a render hint
  205. \param hint Render hint
  206. \return true/false
  207. \sa setRenderHint(), RenderHint
  208. */
  209. bool QwtPlotItem::testRenderHint( RenderHint hint ) const
  210. {
  211. return ( d_data->renderHints & hint );
  212. }
  213. //! Show the item
  214. void QwtPlotItem::show()
  215. {
  216. setVisible( true );
  217. }
  218. //! Hide the item
  219. void QwtPlotItem::hide()
  220. {
  221. setVisible( false );
  222. }
  223. /*!
  224. Show/Hide the item
  225. \param on Show if true, otherwise hide
  226. \sa isVisible(), show(), hide()
  227. */
  228. void QwtPlotItem::setVisible( bool on )
  229. {
  230. if ( on != d_data->isVisible )
  231. {
  232. d_data->isVisible = on;
  233. itemChanged();
  234. }
  235. }
  236. /*!
  237. \return true if visible
  238. \sa setVisible(), show(), hide()
  239. */
  240. bool QwtPlotItem::isVisible() const
  241. {
  242. return d_data->isVisible;
  243. }
  244. /*!
  245. Update the legend and call QwtPlot::autoRefresh for the
  246. parent plot.
  247. \sa updateLegend()
  248. */
  249. void QwtPlotItem::itemChanged()
  250. {
  251. if ( d_data->plot )
  252. {
  253. if ( d_data->plot->legend() )
  254. updateLegend( d_data->plot->legend() );
  255. d_data->plot->autoRefresh();
  256. }
  257. }
  258. /*!
  259. Set X and Y axis
  260. The item will painted according to the coordinates its Axes.
  261. \param xAxis X Axis
  262. \param yAxis Y Axis
  263. \sa setXAxis(), setYAxis(), xAxis(), yAxis()
  264. */
  265. void QwtPlotItem::setAxes( int xAxis, int yAxis )
  266. {
  267. if ( xAxis == QwtPlot::xBottom || xAxis == QwtPlot::xTop )
  268. d_data->xAxis = xAxis;
  269. if ( yAxis == QwtPlot::yLeft || yAxis == QwtPlot::yRight )
  270. d_data->yAxis = yAxis;
  271. itemChanged();
  272. }
  273. /*!
  274. Set the X axis
  275. The item will painted according to the coordinates its Axes.
  276. \param axis X Axis
  277. \sa setAxes(), setYAxis(), xAxis()
  278. */
  279. void QwtPlotItem::setXAxis( int axis )
  280. {
  281. if ( axis == QwtPlot::xBottom || axis == QwtPlot::xTop )
  282. {
  283. d_data->xAxis = axis;
  284. itemChanged();
  285. }
  286. }
  287. /*!
  288. Set the Y axis
  289. The item will painted according to the coordinates its Axes.
  290. \param axis Y Axis
  291. \sa setAxes(), setXAxis(), yAxis()
  292. */
  293. void QwtPlotItem::setYAxis( int axis )
  294. {
  295. if ( axis == QwtPlot::yLeft || axis == QwtPlot::yRight )
  296. {
  297. d_data->yAxis = axis;
  298. itemChanged();
  299. }
  300. }
  301. //! Return xAxis
  302. int QwtPlotItem::xAxis() const
  303. {
  304. return d_data->xAxis;
  305. }
  306. //! Return yAxis
  307. int QwtPlotItem::yAxis() const
  308. {
  309. return d_data->yAxis;
  310. }
  311. /*!
  312. \return An invalid bounding rect: QRectF(1.0, 1.0, -2.0, -2.0)
  313. */
  314. QRectF QwtPlotItem::boundingRect() const
  315. {
  316. return QRectF( 1.0, 1.0, -2.0, -2.0 ); // invalid
  317. }
  318. /*!
  319. \brief Allocate the widget that represents the item on the legend
  320. The default implementation returns a QwtLegendItem(), but an item
  321. could be represented by any type of widget,
  322. by overloading legendItem() and updateLegend().
  323. \return QwtLegendItem()
  324. \sa updateLegend() QwtLegend()
  325. */
  326. QWidget *QwtPlotItem::legendItem() const
  327. {
  328. QwtLegendItem *item = new QwtLegendItem;
  329. if ( d_data->plot )
  330. {
  331. QObject::connect( item, SIGNAL( clicked() ),
  332. d_data->plot, SLOT( legendItemClicked() ) );
  333. QObject::connect( item, SIGNAL( checked( bool ) ),
  334. d_data->plot, SLOT( legendItemChecked( bool ) ) );
  335. }
  336. return item;
  337. }
  338. /*!
  339. \brief Update the widget that represents the item on the legend
  340. updateLegend() is called from itemChanged() to adopt the widget
  341. representing the item on the legend to its new configuration.
  342. The default implementation updates a QwtLegendItem(),
  343. but an item could be represented by any type of widget,
  344. by overloading legendItem() and updateLegend().
  345. \param legend Legend
  346. \sa legendItem(), itemChanged(), QwtLegend()
  347. */
  348. void QwtPlotItem::updateLegend( QwtLegend *legend ) const
  349. {
  350. if ( legend == NULL )
  351. return;
  352. QWidget *lgdItem = legend->find( this );
  353. if ( testItemAttribute( QwtPlotItem::Legend ) )
  354. {
  355. if ( lgdItem == NULL )
  356. {
  357. lgdItem = legendItem();
  358. if ( lgdItem )
  359. legend->insert( this, lgdItem );
  360. }
  361. if ( lgdItem && lgdItem->inherits( "QwtLegendItem" ) )
  362. {
  363. QwtLegendItem* label = ( QwtLegendItem* )lgdItem;
  364. if ( label )
  365. {
  366. // paint the identifier
  367. const QSize sz = label->identifierSize();
  368. QPixmap identifier( sz.width(), sz.height() );
  369. identifier.fill( Qt::transparent );
  370. QPainter painter( &identifier );
  371. painter.setRenderHint( QPainter::Antialiasing,
  372. testRenderHint( QwtPlotItem::RenderAntialiased ) );
  373. drawLegendIdentifier( &painter,
  374. QRect( 0, 0, sz.width(), sz.height() ) );
  375. painter.end();
  376. const bool doUpdate = label->updatesEnabled();
  377. if ( doUpdate )
  378. label->setUpdatesEnabled( false );
  379. label->setText( title() );
  380. label->setIdentifier( identifier );
  381. label->setItemMode( legend->itemMode() );
  382. if ( doUpdate )
  383. label->setUpdatesEnabled( true );
  384. label->update();
  385. }
  386. }
  387. }
  388. else
  389. {
  390. if ( lgdItem )
  391. {
  392. lgdItem->hide();
  393. lgdItem->deleteLater();
  394. }
  395. }
  396. }
  397. /*!
  398. \brief Update the item to changes of the axes scale division
  399. Update the item, when the axes of plot have changed.
  400. The default implementation does nothing, but items that depend
  401. on the scale division (like QwtPlotGrid()) have to reimplement
  402. updateScaleDiv()
  403. \param xScaleDiv Scale division of the x-axis
  404. \param yScaleDiv Scale division of the y-axis
  405. \sa QwtPlot::updateAxes()
  406. */
  407. void QwtPlotItem::updateScaleDiv( const QwtScaleDiv &,
  408. const QwtScaleDiv & )
  409. {
  410. }
  411. /*!
  412. \brief Calculate the bounding scale rect of 2 maps
  413. \param xMap X map
  414. \param yMap X map
  415. \return Bounding scale rect of the scale maps, normalized
  416. */
  417. QRectF QwtPlotItem::scaleRect( const QwtScaleMap &xMap,
  418. const QwtScaleMap &yMap ) const
  419. {
  420. return QRectF( xMap.s1(), yMap.s1(),
  421. xMap.sDist(), yMap.sDist() );
  422. }
  423. /*!
  424. \brief Calculate the bounding paint rect of 2 maps
  425. \param xMap X map
  426. \param yMap X map
  427. \return Bounding paint rect of the scale maps, normalized
  428. */
  429. QRectF QwtPlotItem::paintRect( const QwtScaleMap &xMap,
  430. const QwtScaleMap &yMap ) const
  431. {
  432. const QRectF rect( xMap.p1(), yMap.p1(),
  433. xMap.pDist(), yMap.pDist() );
  434. return rect;
  435. }