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

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