PageRenderTime 25ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/lib/qwt/qwt_plot_scaleitem.cpp

https://github.com/khangbotics/qgroundcontrol
C++ | 453 lines | 252 code | 51 blank | 150 comment | 52 complexity | 437f4c9e227f4f0115253615d985a158 MD5 | raw file
  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 <qpalette.h>
  10. #include <qpainter.h>
  11. #include "qwt_plot.h"
  12. #include "qwt_plot_canvas.h"
  13. #include "qwt_scale_map.h"
  14. #include "qwt_plot_scaleitem.h"
  15. #include "qwt_double_interval.h"
  16. class QwtPlotScaleItem::PrivateData
  17. {
  18. public:
  19. PrivateData():
  20. position(0.0),
  21. borderDistance(-1),
  22. scaleDivFromAxis(true),
  23. scaleDraw(new QwtScaleDraw()) {
  24. }
  25. ~PrivateData() {
  26. delete scaleDraw;
  27. }
  28. #if QT_VERSION < 0x040000
  29. QColorGroup colorGroup;
  30. #else
  31. QPalette palette;
  32. #endif
  33. QFont font;
  34. double position;
  35. int borderDistance;
  36. bool scaleDivFromAxis;
  37. QwtScaleDraw *scaleDraw;
  38. QRect canvasRectCache;
  39. };
  40. /*!
  41. \brief Constructor for scale item at the position pos.
  42. \param alignment In case of QwtScaleDraw::BottomScale/QwtScaleDraw::TopScale
  43. the scale item is corresponding to the xAxis(),
  44. otherwise it corresponds to the yAxis().
  45. \param position x or y position, depending on the corresponding axis.
  46. \sa setPosition(), setAlignment()
  47. */
  48. QwtPlotScaleItem::QwtPlotScaleItem(
  49. QwtScaleDraw::Alignment alignment, const double pos):
  50. QwtPlotItem(QwtText("Scale"))
  51. {
  52. d_data = new PrivateData;
  53. d_data->position = pos;
  54. d_data->scaleDraw->setAlignment(alignment);
  55. setZ(11.0);
  56. }
  57. //! Destructor
  58. QwtPlotScaleItem::~QwtPlotScaleItem()
  59. {
  60. delete d_data;
  61. }
  62. //! \return QwtPlotItem::Rtti_PlotScale
  63. int QwtPlotScaleItem::rtti() const
  64. {
  65. return QwtPlotItem::Rtti_PlotScale;
  66. }
  67. /*!
  68. \brief Assign a scale division
  69. When assigning a scaleDiv the scale division won't be synchronized
  70. with the corresponding axis anymore.
  71. \param scaleDiv Scale division
  72. \sa scaleDiv(), setScaleDivFromAxis(), isScaleDivFromAxis()
  73. */
  74. void QwtPlotScaleItem::setScaleDiv(const QwtScaleDiv& scaleDiv)
  75. {
  76. d_data->scaleDivFromAxis = false;
  77. d_data->scaleDraw->setScaleDiv(scaleDiv);
  78. }
  79. //! \return Scale division
  80. const QwtScaleDiv& QwtPlotScaleItem::scaleDiv() const
  81. {
  82. return d_data->scaleDraw->scaleDiv();
  83. }
  84. /*!
  85. Enable/Disable the synchronization of the scale division with
  86. the corresponding axis.
  87. \sa isScaleDivFromAxis()
  88. */
  89. void QwtPlotScaleItem::setScaleDivFromAxis(bool on)
  90. {
  91. if ( on != d_data->scaleDivFromAxis ) {
  92. d_data->scaleDivFromAxis = on;
  93. if ( on ) {
  94. const QwtPlot *plt = plot();
  95. if ( plt ) {
  96. updateScaleDiv( *plt->axisScaleDiv(xAxis()),
  97. *plt->axisScaleDiv(yAxis()) );
  98. itemChanged();
  99. }
  100. }
  101. }
  102. }
  103. /*!
  104. \return True, if the synchronization of the scale division with
  105. the corresponding axis is enabled.
  106. \sa setScaleDiv(), setScaleDivFromAxis()
  107. */
  108. bool QwtPlotScaleItem::isScaleDivFromAxis() const
  109. {
  110. return d_data->scaleDivFromAxis;
  111. }
  112. #if QT_VERSION < 0x040000
  113. /*!
  114. Set the color group
  115. \sa QwtAbstractScaleDraw::draw(), colorGroup()
  116. */
  117. void QwtPlotScaleItem::setColorGroup(const QColorGroup &colorGroup)
  118. {
  119. if ( colorGroup != d_data->colorGroup ) {
  120. d_data->colorGroup = colorGroup;
  121. itemChanged();
  122. }
  123. }
  124. /*!
  125. \return color group
  126. \sa setColorGroup()
  127. */
  128. QColorGroup QwtPlotScaleItem::colorGroup() const
  129. {
  130. return d_data->colorGroup;
  131. }
  132. #else
  133. /*!
  134. Set the palette
  135. \sa QwtAbstractScaleDraw::draw(), palette()
  136. */
  137. void QwtPlotScaleItem::setPalette(const QPalette &palette)
  138. {
  139. if ( palette != d_data->palette ) {
  140. d_data->palette = palette;
  141. itemChanged();
  142. }
  143. }
  144. /*!
  145. \return palette
  146. \sa setPalette()
  147. */
  148. QPalette QwtPlotScaleItem::palette() const
  149. {
  150. return d_data->palette;
  151. }
  152. #endif
  153. /*!
  154. Change the tick label font
  155. \sa font
  156. */
  157. void QwtPlotScaleItem::setFont(const QFont &font)
  158. {
  159. if ( font != d_data->font ) {
  160. d_data->font = font;
  161. itemChanged();
  162. }
  163. }
  164. /*!
  165. \return tick label font
  166. \sa setFont()
  167. */
  168. QFont QwtPlotScaleItem::font() const
  169. {
  170. return d_data->font;
  171. }
  172. /*!
  173. \brief Set a scale draw
  174. \param axisId axis index
  175. \param scaleDraw object responsible for drawing scales.
  176. The main use case for replacing the default QwtScaleDraw is
  177. to overload QwtAbstractScaleDraw::label, to replace or swallow
  178. tick labels.
  179. \sa scaleDraw()
  180. */
  181. void QwtPlotScaleItem::setScaleDraw(QwtScaleDraw *scaleDraw)
  182. {
  183. if ( scaleDraw == NULL )
  184. return;
  185. if ( scaleDraw != d_data->scaleDraw )
  186. delete d_data->scaleDraw;
  187. d_data->scaleDraw = scaleDraw;
  188. const QwtPlot *plt = plot();
  189. if ( plt ) {
  190. updateScaleDiv( *plt->axisScaleDiv(xAxis()),
  191. *plt->axisScaleDiv(yAxis()) );
  192. }
  193. itemChanged();
  194. }
  195. /*!
  196. \return Scale draw
  197. \sa setScaleDraw()
  198. */
  199. const QwtScaleDraw *QwtPlotScaleItem::scaleDraw() const
  200. {
  201. return d_data->scaleDraw;
  202. }
  203. /*!
  204. \return Scale draw
  205. \sa setScaleDraw()
  206. */
  207. QwtScaleDraw *QwtPlotScaleItem::scaleDraw()
  208. {
  209. return d_data->scaleDraw;
  210. }
  211. /*!
  212. Change the position of the scale
  213. The position is interpreted as y value for horizontal axes
  214. and as x value for vertical axes.
  215. The border distance is set to -1.
  216. \sa position(), setAlignment()
  217. */
  218. void QwtPlotScaleItem::setPosition(double pos)
  219. {
  220. if ( d_data->position != pos ) {
  221. d_data->position = pos;
  222. d_data->borderDistance = -1;
  223. itemChanged();
  224. }
  225. }
  226. /*!
  227. \return Position of the scale
  228. \sa setPosition(), setAlignment()
  229. */
  230. double QwtPlotScaleItem::position() const
  231. {
  232. return d_data->position;
  233. }
  234. /*!
  235. \brief Align the scale to the canvas
  236. If distance is >= 0 the scale will be aligned to a
  237. border of the contents rect of the canvas. If
  238. alignment() is QwtScaleDraw::LeftScale, the scale will
  239. be aligned to the right border, if it is QwtScaleDraw::TopScale
  240. it will be aligned to the bottom (and vice versa),
  241. If distance is < 0 the scale will be at the position().
  242. \param distance Number of pixels between the canvas border and the
  243. backbone of the scale.
  244. \sa setPosition(), borderDistance()
  245. */
  246. void QwtPlotScaleItem::setBorderDistance(int distance)
  247. {
  248. if ( distance < 0 )
  249. distance = -1;
  250. if ( distance != d_data->borderDistance ) {
  251. d_data->borderDistance = distance;
  252. itemChanged();
  253. }
  254. }
  255. /*!
  256. \return Distance from a canvas border
  257. \sa setBorderDistance(), setPosition()
  258. */
  259. int QwtPlotScaleItem::borderDistance() const
  260. {
  261. return d_data->borderDistance;
  262. }
  263. /*!
  264. Change the alignment of the scale
  265. The alignment sets the orientation of the scale and the position of
  266. the ticks:
  267. - QwtScaleDraw::BottomScale: horizontal, ticks below
  268. - QwtScaleDraw::TopScale: horizontal, ticks above
  269. - QwtScaleDraw::LeftScale: vertical, ticks left
  270. - QwtScaleDraw::RightScale: vertical, ticks right
  271. For horizontal scales the position corresponds to QwtPlotItem::yAxis(),
  272. otherwise to QwtPlotItem::xAxis().
  273. \sa scaleDraw(), QwtScaleDraw::alignment(), setPosition()
  274. */
  275. void QwtPlotScaleItem::setAlignment(QwtScaleDraw::Alignment alignment)
  276. {
  277. QwtScaleDraw *sd = d_data->scaleDraw;
  278. if ( sd->alignment() != alignment ) {
  279. sd->setAlignment(alignment);
  280. itemChanged();
  281. }
  282. }
  283. /*!
  284. \brief Draw the scale
  285. */
  286. void QwtPlotScaleItem::draw(QPainter *painter,
  287. const QwtScaleMap &xMap, const QwtScaleMap &yMap,
  288. const QRect &canvasRect) const
  289. {
  290. if ( canvasRect != d_data->canvasRectCache ) {
  291. QwtPlotScaleItem* that = (QwtPlotScaleItem*)this;
  292. that->updateBorders();
  293. }
  294. QPen pen = painter->pen();
  295. pen.setStyle(Qt::SolidLine);
  296. painter->setPen(pen);
  297. int pw = painter->pen().width();
  298. if ( pw == 0 )
  299. pw = 1;
  300. QwtScaleDraw *sd = d_data->scaleDraw;
  301. if ( sd->orientation() == Qt::Horizontal ) {
  302. int y;
  303. if ( d_data->borderDistance >= 0 ) {
  304. if ( sd->alignment() == QwtScaleDraw::BottomScale )
  305. y = canvasRect.top() + d_data->borderDistance;
  306. else {
  307. y = canvasRect.bottom() - d_data->borderDistance - pw + 1;
  308. }
  309. } else {
  310. y = yMap.transform(d_data->position);
  311. }
  312. if ( y < canvasRect.top() || y > canvasRect.bottom() )
  313. return;
  314. sd->move(canvasRect.left(), y);
  315. sd->setLength(canvasRect.width() - 1);
  316. sd->setTransformation(xMap.transformation()->copy());
  317. } else { // == Qt::Vertical
  318. int x;
  319. if ( d_data->borderDistance >= 0 ) {
  320. if ( sd->alignment() == QwtScaleDraw::RightScale )
  321. x = canvasRect.left() + d_data->borderDistance;
  322. else {
  323. x = canvasRect.right() - d_data->borderDistance - pw + 1;
  324. }
  325. } else {
  326. x = xMap.transform(d_data->position);
  327. }
  328. if ( x < canvasRect.left() || x > canvasRect.right() )
  329. return;
  330. sd->move(x, canvasRect.top());
  331. sd->setLength(canvasRect.height() - 1);
  332. sd->setTransformation(yMap.transformation()->copy());
  333. }
  334. painter->setFont(d_data->font);
  335. #if QT_VERSION < 0x040000
  336. sd->draw(painter, d_data->colorGroup);
  337. #else
  338. sd->draw(painter, d_data->palette);
  339. #endif
  340. }
  341. /*!
  342. \brief Update the item to changes of the axes scale division
  343. In case of isScaleDivFromAxis(), the scale draw is synchronized
  344. to the correspond axis.
  345. \param xScaleDiv Scale division of the x-axis
  346. \param yScaleDiv Scale division of the y-axis
  347. \sa QwtPlot::updateAxes()
  348. */
  349. void QwtPlotScaleItem::updateScaleDiv(const QwtScaleDiv& xScaleDiv,
  350. const QwtScaleDiv& yScaleDiv)
  351. {
  352. QwtScaleDraw *sd = d_data->scaleDraw;
  353. if ( d_data->scaleDivFromAxis && sd ) {
  354. sd->setScaleDiv(
  355. sd->orientation() == Qt::Horizontal ? xScaleDiv : yScaleDiv);
  356. updateBorders();
  357. }
  358. }
  359. void QwtPlotScaleItem::updateBorders()
  360. {
  361. const QwtPlot *plt = plot();
  362. if ( plt == NULL || !d_data->scaleDivFromAxis )
  363. return;
  364. const QRect r = plt->canvas()->contentsRect();
  365. d_data->canvasRectCache = r;
  366. QwtDoubleInterval interval;
  367. if ( d_data->scaleDraw->orientation() == Qt::Horizontal ) {
  368. const QwtScaleMap map = plt->canvasMap(xAxis());
  369. interval.setMinValue(map.invTransform(r.left()));
  370. interval.setMaxValue(map.invTransform(r.right()));
  371. } else {
  372. const QwtScaleMap map = plt->canvasMap(yAxis());
  373. interval.setMinValue(map.invTransform(r.bottom()));
  374. interval.setMaxValue(map.invTransform(r.top()));
  375. }
  376. QwtScaleDiv scaleDiv = d_data->scaleDraw->scaleDiv();
  377. scaleDiv.setInterval(interval);
  378. d_data->scaleDraw->setScaleDiv(scaleDiv);
  379. }