/src/qwt/src/qwt_dial_needle.cpp

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