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

Last change on this file since 6935 was 4271, checked in by mervart, 12 years ago
File size: 9.4 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 scldiv;
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 \sa enableComponent()
89*/
90bool QwtAbstractScaleDraw::hasComponent( ScaleComponent component ) const
91{
92 return ( d_data->components & component );
93}
94
95/*!
96 Change the scale division
97 \param sd New scale division
98*/
99void QwtAbstractScaleDraw::setScaleDiv( const QwtScaleDiv &sd )
100{
101 d_data->scldiv = sd;
102 d_data->map.setScaleInterval( sd.lowerBound(), sd.upperBound() );
103 d_data->labelCache.clear();
104}
105
106/*!
107 Change the transformation of the scale
108 \param transformation New scale transformation
109*/
110void QwtAbstractScaleDraw::setTransformation(
111 QwtScaleTransformation *transformation )
112{
113 d_data->map.setTransformation( transformation );
114}
115
116//! \return Map how to translate between scale and pixel values
117const QwtScaleMap &QwtAbstractScaleDraw::scaleMap() const
118{
119 return d_data->map;
120}
121
122//! \return Map how to translate between scale and pixel values
123QwtScaleMap &QwtAbstractScaleDraw::scaleMap()
124{
125 return d_data->map;
126}
127
128//! \return scale division
129const QwtScaleDiv& QwtAbstractScaleDraw::scaleDiv() const
130{
131 return d_data->scldiv;
132}
133
134/*!
135 \brief Specify the width of the scale pen
136 \param width Pen width
137 \sa penWidth()
138*/
139void QwtAbstractScaleDraw::setPenWidth( int width )
140{
141 if ( width < 0 )
142 width = 0;
143
144 if ( width != d_data->penWidth )
145 d_data->penWidth = width;
146}
147
148/*!
149 \return Scale pen width
150 \sa setPenWidth()
151*/
152int QwtAbstractScaleDraw::penWidth() const
153{
154 return d_data->penWidth;
155}
156
157/*!
158 \brief Draw the scale
159
160 \param painter The painter
161
162 \param palette Palette, text color is used for the labels,
163 foreground color for ticks and backbone
164*/
165void QwtAbstractScaleDraw::draw( QPainter *painter,
166 const QPalette& palette ) const
167{
168 painter->save();
169
170 QPen pen = painter->pen();
171 pen.setWidth( d_data->penWidth );
172 pen.setCosmetic( false );
173 painter->setPen( pen );
174
175 if ( hasComponent( QwtAbstractScaleDraw::Labels ) )
176 {
177 painter->save();
178 painter->setPen( palette.color( QPalette::Text ) ); // ignore pen style
179
180 const QList<double> &majorTicks =
181 d_data->scldiv.ticks( QwtScaleDiv::MajorTick );
182
183 for ( int i = 0; i < majorTicks.count(); i++ )
184 {
185 const double v = majorTicks[i];
186 if ( d_data->scldiv.contains( v ) )
187 drawLabel( painter, majorTicks[i] );
188 }
189
190 painter->restore();
191 }
192
193 if ( hasComponent( QwtAbstractScaleDraw::Ticks ) )
194 {
195 painter->save();
196
197 QPen pen = painter->pen();
198 pen.setColor( palette.color( QPalette::WindowText ) );
199 pen.setCapStyle( Qt::FlatCap );
200
201 painter->setPen( pen );
202
203 for ( int tickType = QwtScaleDiv::MinorTick;
204 tickType < QwtScaleDiv::NTickTypes; tickType++ )
205 {
206 const QList<double> &ticks = d_data->scldiv.ticks( tickType );
207 for ( int i = 0; i < ticks.count(); i++ )
208 {
209 const double v = ticks[i];
210 if ( d_data->scldiv.contains( v ) )
211 drawTick( painter, v, d_data->tickLength[tickType] );
212 }
213 }
214
215 painter->restore();
216 }
217
218 if ( hasComponent( QwtAbstractScaleDraw::Backbone ) )
219 {
220 painter->save();
221
222 QPen pen = painter->pen();
223 pen.setColor( palette.color( QPalette::WindowText ) );
224 pen.setCapStyle( Qt::FlatCap );
225
226 painter->setPen( pen );
227
228 drawBackbone( painter );
229
230 painter->restore();
231 }
232
233 painter->restore();
234}
235
236/*!
237 \brief Set the spacing between tick and labels
238
239 The spacing is the distance between ticks and labels.
240 The default spacing is 4 pixels.
241
242 \param spacing Spacing
243
244 \sa spacing()
245*/
246void QwtAbstractScaleDraw::setSpacing( double spacing )
247{
248 if ( spacing < 0 )
249 spacing = 0;
250
251 d_data->spacing = spacing;
252}
253
254/*!
255 \brief Get the spacing
256
257 The spacing is the distance between ticks and labels.
258 The default spacing is 4 pixels.
259
260 \sa setSpacing()
261*/
262double QwtAbstractScaleDraw::spacing() const
263{
264 return d_data->spacing;
265}
266
267/*!
268 \brief Set a minimum for the extent
269
270 The extent is calculated from the coomponents of the
271 scale draw. In situations, where the labels are
272 changing and the layout depends on the extent (f.e scrolling
273 a scale), setting an upper limit as minimum extent will
274 avoid jumps of the layout.
275
276 \param minExtent Minimum extent
277
278 \sa extent(), minimumExtent()
279*/
280void QwtAbstractScaleDraw::setMinimumExtent( double minExtent )
281{
282 if ( minExtent < 0.0 )
283 minExtent = 0.0;
284
285 d_data->minExtent = minExtent;
286}
287
288/*!
289 Get the minimum extent
290 \sa extent(), setMinimumExtent()
291*/
292double QwtAbstractScaleDraw::minimumExtent() const
293{
294 return d_data->minExtent;
295}
296
297/*!
298 Set the length of the ticks
299
300 \param tickType Tick type
301 \param length New length
302
303 \warning the length is limited to [0..1000]
304*/
305void QwtAbstractScaleDraw::setTickLength(
306 QwtScaleDiv::TickType tickType, double length )
307{
308 if ( tickType < QwtScaleDiv::MinorTick ||
309 tickType > QwtScaleDiv::MajorTick )
310 {
311 return;
312 }
313
314 if ( length < 0.0 )
315 length = 0.0;
316
317 const double maxTickLen = 1000.0;
318 if ( length > maxTickLen )
319 length = maxTickLen;
320
321 d_data->tickLength[tickType] = length;
322}
323
324/*!
325 Return the length of the ticks
326
327 \sa setTickLength(), maxTickLength()
328*/
329double QwtAbstractScaleDraw::tickLength( QwtScaleDiv::TickType tickType ) const
330{
331 if ( tickType < QwtScaleDiv::MinorTick ||
332 tickType > QwtScaleDiv::MajorTick )
333 {
334 return 0;
335 }
336
337 return d_data->tickLength[tickType];
338}
339
340/*!
341 \return Length of the longest tick
342
343 Useful for layout calculations
344 \sa tickLength(), setTickLength()
345*/
346double QwtAbstractScaleDraw::maxTickLength() const
347{
348 double length = 0.0;
349 for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ )
350 length = qMax( length, d_data->tickLength[i] );
351
352 return length;
353}
354
355/*!
356 \brief Convert a value into its representing label
357
358 The value is converted to a plain text using
359 QLocale::system().toString(value).
360 This method is often overloaded by applications to have individual
361 labels.
362
363 \param value Value
364 \return Label string.
365*/
366QwtText QwtAbstractScaleDraw::label( double value ) const
367{
368 return QLocale().toString( value );
369}
370
371/*!
372 \brief Convert a value into its representing label and cache it.
373
374 The conversion between value and label is called very often
375 in the layout and painting code. Unfortunately the
376 calculation of the label sizes might be slow (really slow
377 for rich text in Qt4), so it's necessary to cache the labels.
378
379 \param font Font
380 \param value Value
381
382 \return Tick label
383*/
384const QwtText &QwtAbstractScaleDraw::tickLabel(
385 const QFont &font, double value ) const
386{
387 QMap<double, QwtText>::const_iterator it = d_data->labelCache.find( value );
388 if ( it == d_data->labelCache.end() )
389 {
390 QwtText lbl = label( value );
391 lbl.setRenderFlags( 0 );
392 lbl.setLayoutAttribute( QwtText::MinimumLayout );
393
394 ( void )lbl.textSize( font ); // initialize the internal cache
395
396 it = d_data->labelCache.insert( value, lbl );
397 }
398
399 return ( *it );
400}
401
402/*!
403 Invalidate the cache used by QwtAbstractScaleDraw::tickLabel
404
405 The cache is invalidated, when a new QwtScaleDiv is set. If
406 the labels need to be changed. while the same QwtScaleDiv is set,
407 invalidateCache() needs to be called manually.
408*/
409void QwtAbstractScaleDraw::invalidateCache()
410{
411 d_data->labelCache.clear();
412}
Note: See TracBrowser for help on using the repository browser.