qwt_abstract_scale_draw.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  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_abstract_scale_draw.h"
  10. #include "qwt_math.h"
  11. #include "qwt_text.h"
  12. #include "qwt_painter.h"
  13. #include "qwt_scale_map.h"
  14. #include <qpainter.h>
  15. #include <qpalette.h>
  16. #include <qmap.h>
  17. #include <qlocale.h>
  18. class QwtAbstractScaleDraw::PrivateData
  19. {
  20. public:
  21. PrivateData():
  22. components( Backbone | Ticks | Labels ),
  23. spacing( 4.0 ),
  24. penWidth( 0 ),
  25. minExtent( 0.0 )
  26. {
  27. tickLength[QwtScaleDiv::MinorTick] = 4.0;
  28. tickLength[QwtScaleDiv::MediumTick] = 6.0;
  29. tickLength[QwtScaleDiv::MajorTick] = 8.0;
  30. }
  31. int components;
  32. QwtScaleMap map;
  33. QwtScaleDiv scldiv;
  34. double spacing;
  35. double tickLength[QwtScaleDiv::NTickTypes];
  36. int penWidth;
  37. double minExtent;
  38. QMap<double, QwtText> labelCache;
  39. };
  40. /*!
  41. \brief Constructor
  42. The range of the scale is initialized to [0, 100],
  43. The spacing (distance between ticks and labels) is
  44. set to 4, the tick lengths are set to 4,6 and 8 pixels
  45. */
  46. QwtAbstractScaleDraw::QwtAbstractScaleDraw()
  47. {
  48. d_data = new QwtAbstractScaleDraw::PrivateData;
  49. }
  50. //! Destructor
  51. QwtAbstractScaleDraw::~QwtAbstractScaleDraw()
  52. {
  53. delete d_data;
  54. }
  55. /*!
  56. En/Disable a component of the scale
  57. \param component Scale component
  58. \param enable On/Off
  59. \sa hasComponent()
  60. */
  61. void QwtAbstractScaleDraw::enableComponent(
  62. ScaleComponent component, bool enable )
  63. {
  64. if ( enable )
  65. d_data->components |= component;
  66. else
  67. d_data->components &= ~component;
  68. }
  69. /*!
  70. Check if a component is enabled
  71. \sa enableComponent()
  72. */
  73. bool QwtAbstractScaleDraw::hasComponent( ScaleComponent component ) const
  74. {
  75. return ( d_data->components & component );
  76. }
  77. /*!
  78. Change the scale division
  79. \param sd New scale division
  80. */
  81. void QwtAbstractScaleDraw::setScaleDiv( const QwtScaleDiv &sd )
  82. {
  83. d_data->scldiv = sd;
  84. d_data->map.setScaleInterval( sd.lowerBound(), sd.upperBound() );
  85. d_data->labelCache.clear();
  86. }
  87. /*!
  88. Change the transformation of the scale
  89. \param transformation New scale transformation
  90. */
  91. void QwtAbstractScaleDraw::setTransformation(
  92. QwtScaleTransformation *transformation )
  93. {
  94. d_data->map.setTransformation( transformation );
  95. }
  96. //! \return Map how to translate between scale and pixel values
  97. const QwtScaleMap &QwtAbstractScaleDraw::map() const
  98. {
  99. return d_data->map;
  100. }
  101. //! \return Map how to translate between scale and pixel values
  102. QwtScaleMap &QwtAbstractScaleDraw::scaleMap()
  103. {
  104. return d_data->map;
  105. }
  106. //! \return scale division
  107. const QwtScaleDiv& QwtAbstractScaleDraw::scaleDiv() const
  108. {
  109. return d_data->scldiv;
  110. }
  111. /*!
  112. \brief Specify the width of the scale pen
  113. \param width Pen width
  114. \sa penWidth()
  115. */
  116. void QwtAbstractScaleDraw::setPenWidth( int width )
  117. {
  118. if ( width < 0 )
  119. width = 0;
  120. if ( width != d_data->penWidth )
  121. d_data->penWidth = width;
  122. }
  123. /*!
  124. \return Scale pen width
  125. \sa setPenWidth()
  126. */
  127. int QwtAbstractScaleDraw::penWidth() const
  128. {
  129. return d_data->penWidth;
  130. }
  131. /*!
  132. \brief Draw the scale
  133. \param painter The painter
  134. \param palette Palette, text color is used for the labels,
  135. foreground color for ticks and backbone
  136. */
  137. void QwtAbstractScaleDraw::draw( QPainter *painter,
  138. const QPalette& palette ) const
  139. {
  140. painter->save();
  141. QPen pen = painter->pen();
  142. pen.setWidth( d_data->penWidth );
  143. pen.setCosmetic( false );
  144. painter->setPen( pen );
  145. if ( hasComponent( QwtAbstractScaleDraw::Labels ) )
  146. {
  147. painter->save();
  148. painter->setPen( palette.color( QPalette::Text ) ); // ignore pen style
  149. const QList<double> &majorTicks =
  150. d_data->scldiv.ticks( QwtScaleDiv::MajorTick );
  151. for ( int i = 0; i < ( int )majorTicks.count(); i++ )
  152. {
  153. const double v = majorTicks[i];
  154. if ( d_data->scldiv.contains( v ) )
  155. drawLabel( painter, majorTicks[i] );
  156. }
  157. painter->restore();
  158. }
  159. if ( hasComponent( QwtAbstractScaleDraw::Ticks ) )
  160. {
  161. painter->save();
  162. QPen pen = painter->pen();
  163. pen.setColor( palette.color( QPalette::WindowText ) );
  164. pen.setCapStyle( Qt::FlatCap );
  165. painter->setPen( pen );
  166. for ( int tickType = QwtScaleDiv::MinorTick;
  167. tickType < QwtScaleDiv::NTickTypes; tickType++ )
  168. {
  169. const QList<double> &ticks = d_data->scldiv.ticks( tickType );
  170. for ( int i = 0; i < ( int )ticks.count(); i++ )
  171. {
  172. const double v = ticks[i];
  173. if ( d_data->scldiv.contains( v ) )
  174. drawTick( painter, v, d_data->tickLength[tickType] );
  175. }
  176. }
  177. painter->restore();
  178. }
  179. if ( hasComponent( QwtAbstractScaleDraw::Backbone ) )
  180. {
  181. painter->save();
  182. QPen pen = painter->pen();
  183. pen.setColor( palette.color( QPalette::WindowText ) );
  184. pen.setCapStyle( Qt::FlatCap );
  185. painter->setPen( pen );
  186. drawBackbone( painter );
  187. painter->restore();
  188. }
  189. painter->restore();
  190. }
  191. /*!
  192. \brief Set the spacing between tick and labels
  193. The spacing is the distance between ticks and labels.
  194. The default spacing is 4 pixels.
  195. \param spacing Spacing
  196. \sa spacing()
  197. */
  198. void QwtAbstractScaleDraw::setSpacing( double spacing )
  199. {
  200. if ( spacing < 0 )
  201. spacing = 0;
  202. d_data->spacing = spacing;
  203. }
  204. /*!
  205. \brief Get the spacing
  206. The spacing is the distance between ticks and labels.
  207. The default spacing is 4 pixels.
  208. \sa setSpacing()
  209. */
  210. double QwtAbstractScaleDraw::spacing() const
  211. {
  212. return d_data->spacing;
  213. }
  214. /*!
  215. \brief Set a minimum for the extent
  216. The extent is calculated from the coomponents of the
  217. scale draw. In situations, where the labels are
  218. changing and the layout depends on the extent (f.e scrolling
  219. a scale), setting an upper limit as minimum extent will
  220. avoid jumps of the layout.
  221. \param minExtent Minimum extent
  222. \sa extent(), minimumExtent()
  223. */
  224. void QwtAbstractScaleDraw::setMinimumExtent( double minExtent )
  225. {
  226. if ( minExtent < 0.0 )
  227. minExtent = 0.0;
  228. d_data->minExtent = minExtent;
  229. }
  230. /*!
  231. Get the minimum extent
  232. \sa extent(), setMinimumExtent()
  233. */
  234. double QwtAbstractScaleDraw::minimumExtent() const
  235. {
  236. return d_data->minExtent;
  237. }
  238. /*!
  239. Set the length of the ticks
  240. \param tickType Tick type
  241. \param length New length
  242. \warning the length is limited to [0..1000]
  243. */
  244. void QwtAbstractScaleDraw::setTickLength(
  245. QwtScaleDiv::TickType tickType, double length )
  246. {
  247. if ( tickType < QwtScaleDiv::MinorTick ||
  248. tickType > QwtScaleDiv::MajorTick )
  249. {
  250. return;
  251. }
  252. if ( length < 0.0 )
  253. length = 0.0;
  254. const double maxTickLen = 1000.0;
  255. if ( length > maxTickLen )
  256. length = maxTickLen;
  257. d_data->tickLength[tickType] = length;
  258. }
  259. /*!
  260. Return the length of the ticks
  261. \sa setTickLength(), majTickLength()
  262. */
  263. double QwtAbstractScaleDraw::tickLength( QwtScaleDiv::TickType tickType ) const
  264. {
  265. if ( tickType < QwtScaleDiv::MinorTick ||
  266. tickType > QwtScaleDiv::MajorTick )
  267. {
  268. return 0;
  269. }
  270. return d_data->tickLength[tickType];
  271. }
  272. /*!
  273. The same as QwtAbstractScaleDraw::tickLength(QwtScaleDiv::MajorTick).
  274. */
  275. double QwtAbstractScaleDraw::majTickLength() const
  276. {
  277. return d_data->tickLength[QwtScaleDiv::MajorTick];
  278. }
  279. /*!
  280. \brief Convert a value into its representing label
  281. The value is converted to a plain text using
  282. QLocale::system().toString(value).
  283. This method is often overloaded by applications to have individual
  284. labels.
  285. \param value Value
  286. \return Label string.
  287. */
  288. QwtText QwtAbstractScaleDraw::label( double value ) const
  289. {
  290. return QLocale::system().toString( value );
  291. }
  292. /*!
  293. \brief Convert a value into its representing label and cache it.
  294. The conversion between value and label is called very often
  295. in the layout and painting code. Unfortunately the
  296. calculation of the label sizes might be slow (really slow
  297. for rich text in Qt4), so it's necessary to cache the labels.
  298. \param font Font
  299. \param value Value
  300. \return Tick label
  301. */
  302. const QwtText &QwtAbstractScaleDraw::tickLabel(
  303. const QFont &font, double value ) const
  304. {
  305. QMap<double, QwtText>::const_iterator it = d_data->labelCache.find( value );
  306. if ( it == d_data->labelCache.end() )
  307. {
  308. QwtText lbl = label( value );
  309. lbl.setRenderFlags( 0 );
  310. lbl.setLayoutAttribute( QwtText::MinimumLayout );
  311. ( void )lbl.textSize( font ); // initialize the internal cache
  312. it = d_data->labelCache.insert( value, lbl );
  313. }
  314. return ( *it );
  315. }
  316. /*!
  317. Invalidate the cache used by QwtAbstractScaleDraw::tickLabel
  318. The cache is invalidated, when a new QwtScaleDiv is set. If
  319. the labels need to be changed. while the same QwtScaleDiv is set,
  320. QwtAbstractScaleDraw::invalidateCache needs to be called manually.
  321. */
  322. void QwtAbstractScaleDraw::invalidateCache()
  323. {
  324. d_data->labelCache.clear();
  325. }