source: ntrip/trunk/BNC/qwt/qwt_abstract_scale_draw.cpp@ 9184

Last change on this file since 9184 was 8127, checked in by stoecker, 7 years ago

update qwt and qwtpolar, many QT5 fixes (unfinished)

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