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

Last change on this file since 8127 was 8127, checked in by stoecker, 2 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.