/src/lib/qwt/qwt_dial_needle.cpp

https://github.com/khangbotics/qgroundcontrol · C++ · 565 lines · 345 code · 101 blank · 119 comment · 27 complexity · 40341a291ae80d0d0cb293565dc0c757 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 <math.h>
  10. #include <qapplication.h>
  11. #include <qpainter.h>
  12. #include "qwt_math.h"
  13. #include "qwt_painter.h"
  14. #include "qwt_polygon.h"
  15. #include "qwt_dial_needle.h"
  16. #if QT_VERSION < 0x040000
  17. typedef QColorGroup QwtPalette;
  18. #else
  19. typedef QPalette QwtPalette;
  20. #endif
  21. //! Constructor
  22. QwtDialNeedle::QwtDialNeedle():
  23. d_palette(QApplication::palette())
  24. {
  25. }
  26. //! Destructor
  27. QwtDialNeedle::~QwtDialNeedle()
  28. {
  29. }
  30. /*!
  31. Sets the palette for the needle.
  32. \param palette New Palette
  33. */
  34. void QwtDialNeedle::setPalette(const QPalette &palette)
  35. {
  36. d_palette = palette;
  37. }
  38. /*!
  39. \return the palette of the needle.
  40. */
  41. const QPalette &QwtDialNeedle::palette() const
  42. {
  43. return d_palette;
  44. }
  45. //! Draw the knob
  46. void QwtDialNeedle::drawKnob(QPainter *painter,
  47. const QPoint &pos, int width, const QBrush &brush, bool sunken)
  48. {
  49. painter->save();
  50. QRect rect(0, 0, width, width);
  51. rect.moveCenter(pos);
  52. painter->setPen(Qt::NoPen);
  53. painter->setBrush(brush);
  54. painter->drawEllipse(rect);
  55. painter->setBrush(Qt::NoBrush);
  56. const int colorOffset = 20;
  57. int startAngle = 45;
  58. if ( sunken )
  59. startAngle += 180;
  60. QPen pen;
  61. pen.setWidth(1);
  62. pen.setColor(brush.color().dark(100 - colorOffset));
  63. painter->setPen(pen);
  64. painter->drawArc(rect, startAngle * 16, 180 * 16);
  65. pen.setColor(brush.color().dark(100 + colorOffset));
  66. painter->setPen(pen);
  67. painter->drawArc(rect, (startAngle + 180) * 16, 180 * 16);
  68. painter->restore();
  69. }
  70. /*!
  71. Constructor
  72. */
  73. QwtDialSimpleNeedle::QwtDialSimpleNeedle(Style style, bool hasKnob,
  74. const QColor &mid, const QColor &base):
  75. d_style(style),
  76. d_hasKnob(hasKnob),
  77. d_width(-1)
  78. {
  79. QPalette palette;
  80. for ( int i = 0; i < QPalette::NColorGroups; i++ ) {
  81. palette.setColor((QPalette::ColorGroup)i,
  82. QwtPalette::Mid, mid);
  83. palette.setColor((QPalette::ColorGroup)i,
  84. QwtPalette::Base, base);
  85. }
  86. setPalette(palette);
  87. }
  88. //! Set the width of the needle
  89. void QwtDialSimpleNeedle::setWidth(int width)
  90. {
  91. d_width = width;
  92. }
  93. /*!
  94. \return the width of the needle
  95. */
  96. int QwtDialSimpleNeedle::width() const
  97. {
  98. return d_width;
  99. }
  100. /*!
  101. Draw the needle
  102. \param painter Painter
  103. \param center Center of the dial, start position for the needle
  104. \param length Length of the needle
  105. \param direction Direction of the needle, in degrees counter clockwise
  106. \param colorGroup Color group, used for painting
  107. */
  108. void QwtDialSimpleNeedle::draw(QPainter *painter, const QPoint &center,
  109. int length, double direction, QPalette::ColorGroup colorGroup) const
  110. {
  111. if ( d_style == Arrow ) {
  112. drawArrowNeedle(painter, palette(), colorGroup,
  113. center, length, d_width, direction, d_hasKnob);
  114. } else {
  115. drawRayNeedle(painter, palette(), colorGroup,
  116. center, length, d_width, direction, d_hasKnob);
  117. }
  118. }
  119. /*!
  120. Draw a needle looking like a ray
  121. */
  122. void QwtDialSimpleNeedle::drawRayNeedle(QPainter *painter,
  123. const QPalette &palette, QPalette::ColorGroup colorGroup,
  124. const QPoint &center, int length, int width, double direction,
  125. bool hasKnob)
  126. {
  127. if ( width <= 0 )
  128. width = 5;
  129. direction *= M_PI / 180.0;
  130. painter->save();
  131. const QPoint p1(center.x() + 1, center.y() + 2);
  132. const QPoint p2 = qwtPolar2Pos(p1, length, direction);
  133. if ( width == 1 ) {
  134. const QColor midColor =
  135. palette.color(colorGroup, QwtPalette::Mid);
  136. painter->setPen(QPen(midColor, 1));
  137. painter->drawLine(p1, p2);
  138. } else {
  139. QwtPolygon pa(4);
  140. pa.setPoint(0, qwtPolar2Pos(p1, width / 2, direction + M_PI_2));
  141. pa.setPoint(1, qwtPolar2Pos(p2, width / 2, direction + M_PI_2));
  142. pa.setPoint(2, qwtPolar2Pos(p2, width / 2, direction - M_PI_2));
  143. pa.setPoint(3, qwtPolar2Pos(p1, width / 2, direction - M_PI_2));
  144. painter->setPen(Qt::NoPen);
  145. painter->setBrush(palette.brush(colorGroup, QwtPalette::Mid));
  146. painter->drawPolygon(pa);
  147. }
  148. if ( hasKnob ) {
  149. int knobWidth = qwtMax(qRound(width * 0.7), 5);
  150. if ( knobWidth % 2 == 0 )
  151. knobWidth++;
  152. drawKnob(painter, center, knobWidth,
  153. palette.brush(colorGroup, QwtPalette::Base),
  154. false);
  155. }
  156. painter->restore();
  157. }
  158. /*!
  159. Draw a needle looking like an arrow
  160. */
  161. void QwtDialSimpleNeedle::drawArrowNeedle(QPainter *painter,
  162. const QPalette &palette, QPalette::ColorGroup colorGroup,
  163. const QPoint &center, int length, int width,
  164. double direction, bool hasKnob)
  165. {
  166. direction *= M_PI / 180.0;
  167. painter->save();
  168. if ( width <= 0 ) {
  169. width = (int)qwtMax(length * 0.06, 9.0);
  170. if ( width % 2 == 0 )
  171. width++;
  172. }
  173. const int peak = 3;
  174. const QPoint p1(center.x() + 1, center.y() + 1);
  175. const QPoint p2 = qwtPolar2Pos(p1, length - peak, direction);
  176. const QPoint p3 = qwtPolar2Pos(p1, length, direction);
  177. QwtPolygon pa(5);
  178. pa.setPoint(0, qwtPolar2Pos(p1, width / 2, direction - M_PI_2));
  179. pa.setPoint(1, qwtPolar2Pos(p2, 1, direction - M_PI_2));
  180. pa.setPoint(2, p3);
  181. pa.setPoint(3, qwtPolar2Pos(p2, 1, direction + M_PI_2));
  182. pa.setPoint(4, qwtPolar2Pos(p1, width / 2, direction + M_PI_2));
  183. painter->setPen(Qt::NoPen);
  184. painter->setBrush(palette.brush(colorGroup, QwtPalette::Mid));
  185. painter->drawPolygon(pa);
  186. QwtPolygon shadowPa(3);
  187. const int colorOffset = 10;
  188. int i;
  189. for ( i = 0; i < 3; i++ )
  190. shadowPa.setPoint(i, pa[i]);
  191. const QColor midColor = palette.color(colorGroup, QwtPalette::Mid);
  192. painter->setPen(midColor.dark(100 + colorOffset));
  193. painter->drawPolyline(shadowPa);
  194. for ( i = 0; i < 3; i++ )
  195. shadowPa.setPoint(i, pa[i + 2]);
  196. painter->setPen(midColor.dark(100 - colorOffset));
  197. painter->drawPolyline(shadowPa);
  198. if ( hasKnob ) {
  199. drawKnob(painter, center, qRound(width * 1.3),
  200. palette.brush(colorGroup, QwtPalette::Base),
  201. false);
  202. }
  203. painter->restore();
  204. }
  205. //! Constructor
  206. QwtCompassMagnetNeedle::QwtCompassMagnetNeedle(Style style,
  207. const QColor &light, const QColor &dark):
  208. d_style(style)
  209. {
  210. QPalette palette;
  211. for ( int i = 0; i < QPalette::NColorGroups; i++ ) {
  212. palette.setColor((QPalette::ColorGroup)i,
  213. QwtPalette::Light, light);
  214. palette.setColor((QPalette::ColorGroup)i,
  215. QwtPalette::Dark, dark);
  216. palette.setColor((QPalette::ColorGroup)i,
  217. QwtPalette::Base, Qt::darkGray);
  218. }
  219. setPalette(palette);
  220. }
  221. /*!
  222. Draw the needle
  223. \param painter Painter
  224. \param center Center of the dial, start position for the needle
  225. \param length Length of the needle
  226. \param direction Direction of the needle, in degrees counter clockwise
  227. \param colorGroup Color group, used for painting
  228. */
  229. void QwtCompassMagnetNeedle::draw(QPainter *painter, const QPoint &center,
  230. int length, double direction, QPalette::ColorGroup colorGroup) const
  231. {
  232. if ( d_style == ThinStyle ) {
  233. drawThinNeedle(painter, palette(), colorGroup,
  234. center, length, direction);
  235. } else {
  236. drawTriangleNeedle(painter, palette(), colorGroup,
  237. center, length, direction);
  238. }
  239. }
  240. /*!
  241. Draw a compass needle
  242. \param painter Painter
  243. \param palette Palette
  244. \param colorGroup Color group
  245. \param center Center, where the needle starts
  246. \param length Length of the needle
  247. \param direction Direction
  248. */
  249. void QwtCompassMagnetNeedle::drawTriangleNeedle(QPainter *painter,
  250. const QPalette &palette, QPalette::ColorGroup colorGroup,
  251. const QPoint &center, int length, double direction)
  252. {
  253. const QBrush darkBrush = palette.brush(colorGroup, QwtPalette::Dark);
  254. const QBrush lightBrush = palette.brush(colorGroup, QwtPalette::Light);
  255. QBrush brush;
  256. const int width = qRound(length / 3.0);
  257. const int colorOffset = 10;
  258. painter->save();
  259. painter->setPen(Qt::NoPen);
  260. const QPoint arrowCenter(center.x() + 1, center.y() + 1);
  261. QwtPolygon pa(3);
  262. pa.setPoint(0, arrowCenter);
  263. pa.setPoint(1, qwtDegree2Pos(arrowCenter, length, direction));
  264. pa.setPoint(2, qwtDegree2Pos(arrowCenter, width / 2, direction + 90.0));
  265. brush = darkBrush;
  266. brush.setColor(brush.color().dark(100 + colorOffset));
  267. painter->setBrush(brush);
  268. painter->drawPolygon(pa);
  269. pa.setPoint(2, qwtDegree2Pos(arrowCenter, width / 2, direction - 90.0));
  270. brush = darkBrush;
  271. brush.setColor(brush.color().dark(100 - colorOffset));
  272. painter->setBrush(brush);
  273. painter->drawPolygon(pa);
  274. // --
  275. pa.setPoint(1, qwtDegree2Pos(arrowCenter, length, direction + 180.0));
  276. pa.setPoint(2, qwtDegree2Pos(arrowCenter, width / 2, direction + 90.0));
  277. brush = lightBrush;
  278. brush.setColor(brush.color().dark(100 + colorOffset));
  279. painter->setBrush(brush);
  280. painter->drawPolygon(pa);
  281. pa.setPoint(2, qwtDegree2Pos(arrowCenter, width / 2, direction - 90.0));
  282. brush = lightBrush;
  283. brush.setColor(brush.color().dark(100 - colorOffset));
  284. painter->setBrush(brush);
  285. painter->drawPolygon(pa);
  286. painter->restore();
  287. }
  288. /*!
  289. Draw a compass needle
  290. \param painter Painter
  291. \param palette Palette
  292. \param colorGroup Color group
  293. \param center Center, where the needle starts
  294. \param length Length of the needle
  295. \param direction Direction
  296. */
  297. void QwtCompassMagnetNeedle::drawThinNeedle(QPainter *painter,
  298. const QPalette &palette, QPalette::ColorGroup colorGroup,
  299. const QPoint &center, int length, double direction)
  300. {
  301. const QBrush darkBrush = palette.brush(colorGroup, QwtPalette::Dark);
  302. const QBrush lightBrush = palette.brush(colorGroup, QwtPalette::Light);
  303. const QBrush baseBrush = palette.brush(colorGroup, QwtPalette::Base);
  304. const int colorOffset = 10;
  305. const int width = qwtMax(qRound(length / 6.0), 3);
  306. painter->save();
  307. const QPoint arrowCenter(center.x() + 1, center.y() + 1);
  308. drawPointer(painter, darkBrush, colorOffset,
  309. arrowCenter, length, width, direction);
  310. drawPointer(painter, lightBrush, -colorOffset,
  311. arrowCenter, length, width, direction + 180.0);
  312. drawKnob(painter, arrowCenter, width, baseBrush, true);
  313. painter->restore();
  314. }
  315. /*!
  316. Draw a compass needle
  317. \param painter Painter
  318. \param brush Brush
  319. \param colorOffset Color offset
  320. \param center Center, where the needle starts
  321. \param length Length of the needle
  322. \param width Width of the needle
  323. \param direction Direction
  324. */
  325. void QwtCompassMagnetNeedle::drawPointer(
  326. QPainter *painter, const QBrush &brush,
  327. int colorOffset, const QPoint &center, int length,
  328. int width, double direction)
  329. {
  330. painter->save();
  331. const int peak = qwtMax(qRound(length / 10.0), 5);
  332. const int knobWidth = width + 8;
  333. QRect knobRect(0, 0, knobWidth, knobWidth);
  334. knobRect.moveCenter(center);
  335. QwtPolygon pa(5);
  336. pa.setPoint(0, qwtDegree2Pos(center, width / 2, direction + 90.0));
  337. pa.setPoint(1, center);
  338. pa.setPoint(2, qwtDegree2Pos(pa.point(1), length - peak, direction));
  339. pa.setPoint(3, qwtDegree2Pos(center, length, direction));
  340. pa.setPoint(4, qwtDegree2Pos(pa.point(0), length - peak, direction));
  341. painter->setPen(Qt::NoPen);
  342. QBrush darkBrush = brush;
  343. darkBrush.setColor(darkBrush.color().dark(100 + colorOffset));
  344. painter->setBrush(darkBrush);
  345. painter->drawPolygon(pa);
  346. painter->drawPie(knobRect, qRound(direction * 16), 90 * 16);
  347. pa.setPoint(0, qwtDegree2Pos(center, width / 2, direction - 90.0));
  348. pa.setPoint(4, qwtDegree2Pos(pa.point(0), length - peak, direction));
  349. QBrush lightBrush = brush;
  350. lightBrush.setColor(lightBrush.color().dark(100 - colorOffset));
  351. painter->setBrush(lightBrush);
  352. painter->drawPolygon(pa);
  353. painter->drawPie(knobRect, qRound(direction * 16), -90 * 16);
  354. painter->restore();
  355. }
  356. /*!
  357. Constructor
  358. \param style Arrow style
  359. \param light Light color
  360. \param dark Dark color
  361. */
  362. QwtCompassWindArrow::QwtCompassWindArrow(Style style,
  363. const QColor &light, const QColor &dark):
  364. d_style(style)
  365. {
  366. QPalette palette;
  367. for ( int i = 0; i < QPalette::NColorGroups; i++ ) {
  368. palette.setColor((QPalette::ColorGroup)i,
  369. QwtPalette::Light, light);
  370. palette.setColor((QPalette::ColorGroup)i,
  371. QwtPalette::Dark, dark);
  372. }
  373. setPalette(palette);
  374. }
  375. /*!
  376. Draw the needle
  377. \param painter Painter
  378. \param center Center of the dial, start position for the needle
  379. \param length Length of the needle
  380. \param direction Direction of the needle, in degrees counter clockwise
  381. \param colorGroup Color group, used for painting
  382. */
  383. void QwtCompassWindArrow::draw(QPainter *painter, const QPoint &center,
  384. int length, double direction, QPalette::ColorGroup colorGroup) const
  385. {
  386. if ( d_style == Style1 ) {
  387. drawStyle1Needle(painter, palette(), colorGroup,
  388. center, length, direction);
  389. } else {
  390. drawStyle2Needle(painter, palette(), colorGroup,
  391. center, length, direction);
  392. }
  393. }
  394. /*!
  395. Draw a compass needle
  396. \param painter Painter
  397. \param palette Palette
  398. \param colorGroup colorGroup
  399. \param center Center of the dial, start position for the needle
  400. \param length Length of the needle
  401. \param direction Direction of the needle, in degrees counter clockwise
  402. */
  403. void QwtCompassWindArrow::drawStyle1Needle(QPainter *painter,
  404. const QPalette &palette, QPalette::ColorGroup colorGroup,
  405. const QPoint &center, int length, double direction)
  406. {
  407. const QBrush lightBrush = palette.brush(colorGroup, QwtPalette::Light);
  408. const double AR1[] = {0, 0.4, 0.3, 1, 0.8, 1, 0.3, 0.4};
  409. const double AW1[] = {0, -45, -20, -15, 0, 15, 20, 45};
  410. const QPoint arrowCenter(center.x() + 1, center.y() + 1);
  411. QwtPolygon pa(8);
  412. pa.setPoint(0, arrowCenter);
  413. for (int i=1; i<8; i++) {
  414. const QPoint p = qwtDegree2Pos(center,
  415. AR1[i] * length, direction + AW1[i]);
  416. pa.setPoint(i, p);
  417. }
  418. painter->save();
  419. painter->setPen(Qt::NoPen);
  420. painter->setBrush(lightBrush);
  421. painter->drawPolygon(pa);
  422. painter->restore();
  423. }
  424. /*!
  425. Draw a compass needle
  426. \param painter Painter
  427. \param palette Palette
  428. \param colorGroup colorGroup
  429. \param center Center of the dial, start position for the needle
  430. \param length Length of the needle
  431. \param direction Direction of the needle, in degrees counter clockwise
  432. */
  433. void QwtCompassWindArrow::drawStyle2Needle(QPainter *painter,
  434. const QPalette &palette, QPalette::ColorGroup colorGroup,
  435. const QPoint &center, int length, double direction)
  436. {
  437. const QBrush lightBrush = palette.brush(colorGroup, QwtPalette::Light);
  438. const QBrush darkBrush = palette.brush(colorGroup, QwtPalette::Dark);
  439. painter->save();
  440. painter->setPen(Qt::NoPen);
  441. const double angle = 12.0;
  442. const double ratio = 0.7;
  443. const QPoint arrowCenter(center.x() + 1, center.y() + 1);
  444. QwtPolygon pa(3);
  445. pa.setPoint(0, center);
  446. pa.setPoint(2, qwtDegree2Pos(arrowCenter, ratio * length, direction));
  447. pa.setPoint(1, qwtDegree2Pos(arrowCenter, length, direction + angle));
  448. painter->setBrush(darkBrush);
  449. painter->drawPolygon(pa);
  450. pa.setPoint(1, qwtDegree2Pos(arrowCenter, length, direction - angle));
  451. painter->setBrush(lightBrush);
  452. painter->drawPolygon(pa);
  453. painter->restore();
  454. }