qwt_dial_needle.cpp 17 KB

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