qwt_abstract_scale.cpp 10.2 KB
Newer Older
pixhawk's avatar
pixhawk committed
1 2 3 4
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 * Qwt Widget Library
 * Copyright (C) 1997   Josef Wilgen
 * Copyright (C) 2002   Uwe Rathmann
5
 *
pixhawk's avatar
pixhawk committed
6 7 8 9
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the Qwt License, Version 1.0
 *****************************************************************************/

Bryant's avatar
Bryant committed
10
#include "qwt_abstract_scale.h"
pixhawk's avatar
pixhawk committed
11 12 13 14
#include "qwt_scale_engine.h"
#include "qwt_scale_draw.h"
#include "qwt_scale_div.h"
#include "qwt_scale_map.h"
Bryant's avatar
Bryant committed
15
#include "qwt_interval.h"
pixhawk's avatar
pixhawk committed
16 17 18 19 20

class QwtAbstractScale::PrivateData
{
public:
    PrivateData():
Bryant's avatar
Bryant committed
21 22 23 24 25
        maxMajor( 5 ),
        maxMinor( 3 ),
        stepSize( 0.0 )
    {
        scaleEngine = new QwtLinearScaleEngine();
pixhawk's avatar
pixhawk committed
26 27 28
        scaleDraw = new QwtScaleDraw();
    }

Bryant's avatar
Bryant committed
29 30
    ~PrivateData()
    {
pixhawk's avatar
pixhawk committed
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
        delete scaleEngine;
        delete scaleDraw;
    }

    QwtScaleEngine *scaleEngine;
    QwtAbstractScaleDraw *scaleDraw;

    int maxMajor;
    int maxMinor;
    double stepSize;
};

/*!
  Constructor

Bryant's avatar
Bryant committed
46 47
  \param parent Parent widget

48
  Creates a default QwtScaleDraw and a QwtLinearScaleEngine.
Bryant's avatar
Bryant committed
49 50 51 52
  The initial scale boundaries are set to [ 0.0, 100.0 ]

  The scaleStepSize() is initialized to 0.0, scaleMaxMajor() to 5
  and scaleMaxMajor to 3.
pixhawk's avatar
pixhawk committed
53
*/
54

Bryant's avatar
Bryant committed
55 56
QwtAbstractScale::QwtAbstractScale( QWidget *parent ):
    QWidget( parent )
pixhawk's avatar
pixhawk committed
57 58
{
    d_data = new PrivateData;
Bryant's avatar
Bryant committed
59
    rescale( 0.0, 100.0, d_data->stepSize );
pixhawk's avatar
pixhawk committed
60 61 62 63 64 65 66 67 68
}

//! Destructor
QwtAbstractScale::~QwtAbstractScale()
{
    delete d_data;
}

/*!
Bryant's avatar
Bryant committed
69
  Set the lower bound of the scale
pixhawk's avatar
pixhawk committed
70

Bryant's avatar
Bryant committed
71
  \param value Lower bound
pixhawk's avatar
pixhawk committed
72

Bryant's avatar
Bryant committed
73 74 75
  \sa lowerBound(), setScale(), setUpperBound()
  \note For inverted scales the lower bound 
        is greater than the upper bound
pixhawk's avatar
pixhawk committed
76
*/
Bryant's avatar
Bryant committed
77
void QwtAbstractScale::setLowerBound( double value )
pixhawk's avatar
pixhawk committed
78
{
Bryant's avatar
Bryant committed
79 80
    setScale( value, upperBound() );
}
pixhawk's avatar
pixhawk committed
81

Bryant's avatar
Bryant committed
82 83 84 85 86 87 88
/*!
  \return Lower bound of the scale
  \sa setLowerBound(), setScale(), upperBound()
*/
double QwtAbstractScale::lowerBound() const
{
    return d_data->scaleDraw->scaleDiv().lowerBound();
pixhawk's avatar
pixhawk committed
89 90 91
}

/*!
Bryant's avatar
Bryant committed
92
  Set the upper bound of the scale
pixhawk's avatar
pixhawk committed
93

Bryant's avatar
Bryant committed
94
  \param value Upper bound
pixhawk's avatar
pixhawk committed
95

Bryant's avatar
Bryant committed
96 97 98
  \sa upperBound(), setScale(), setLowerBound()
  \note For inverted scales the lower bound 
        is greater than the upper bound
pixhawk's avatar
pixhawk committed
99
*/
Bryant's avatar
Bryant committed
100
void QwtAbstractScale::setUpperBound( double value )
pixhawk's avatar
pixhawk committed
101
{
Bryant's avatar
Bryant committed
102
    setScale( lowerBound(), value );
pixhawk's avatar
pixhawk committed
103 104
}

Bryant's avatar
Bryant committed
105 106 107 108 109 110 111 112
/*!
  \return Upper bound of the scale
  \sa setUpperBound(), setScale(), lowerBound()
*/
double QwtAbstractScale::upperBound() const
{
    return d_data->scaleDraw->scaleDiv().upperBound();
}
pixhawk's avatar
pixhawk committed
113 114 115 116

/*!
  \brief Specify a scale.

Bryant's avatar
Bryant committed
117
  Define a scale by an interval 
pixhawk's avatar
pixhawk committed
118

Bryant's avatar
Bryant committed
119 120 121 122 123 124 125 126
  The ticks are calculated using scaleMaxMinor(), 
  scaleMaxMajor() and scaleStepSize().

  \param lowerBound lower limit of the scale interval
  \param upperBound upper limit of the scale interval

  \note For inverted scales the lower bound 
        is greater than the upper bound
pixhawk's avatar
pixhawk committed
127
*/
Bryant's avatar
Bryant committed
128
void QwtAbstractScale::setScale( double lowerBound, double upperBound )
pixhawk's avatar
pixhawk committed
129
{
Bryant's avatar
Bryant committed
130
    rescale( lowerBound, upperBound, d_data->stepSize );
pixhawk's avatar
pixhawk committed
131 132 133
}

/*!
Bryant's avatar
Bryant committed
134
  \brief Specify a scale.
pixhawk's avatar
pixhawk committed
135

Bryant's avatar
Bryant committed
136
  Define a scale by an interval
pixhawk's avatar
pixhawk committed
137

Bryant's avatar
Bryant committed
138 139 140 141
  The ticks are calculated using scaleMaxMinor(), 
  scaleMaxMajor() and scaleStepSize().

  \param interval Interval
pixhawk's avatar
pixhawk committed
142
*/
Bryant's avatar
Bryant committed
143
void QwtAbstractScale::setScale( const QwtInterval &interval )
pixhawk's avatar
pixhawk committed
144
{
Bryant's avatar
Bryant committed
145
    setScale( interval.minValue(), interval.maxValue() );
pixhawk's avatar
pixhawk committed
146 147 148
}

/*!
Bryant's avatar
Bryant committed
149
  \brief Specify a scale.
pixhawk's avatar
pixhawk committed
150

Bryant's avatar
Bryant committed
151 152 153 154
  scaleMaxMinor(), scaleMaxMajor() and scaleStepSize() and have no effect.

  \param scaleDiv Scale division
  \sa setAutoScale()
pixhawk's avatar
pixhawk committed
155
*/
Bryant's avatar
Bryant committed
156
void QwtAbstractScale::setScale( const QwtScaleDiv &scaleDiv )
pixhawk's avatar
pixhawk committed
157
{
Bryant's avatar
Bryant committed
158 159 160 161 162 163 164 165 166 167 168 169
    if ( scaleDiv != d_data->scaleDraw->scaleDiv() )
    {
#if 1
        if ( d_data->scaleEngine )
        {
            d_data->scaleDraw->setTransformation(
                d_data->scaleEngine->transformation() );
        }
#endif

        d_data->scaleDraw->setScaleDiv( scaleDiv );

pixhawk's avatar
pixhawk committed
170 171 172 173 174 175 176 177 178
        scaleChange();
    }
}

/*!
  \brief Set the maximum number of major tick intervals.

  The scale's major ticks are calculated automatically such that
  the number of major intervals does not exceed ticks.
Bryant's avatar
Bryant committed
179

pixhawk's avatar
pixhawk committed
180
  The default value is 5.
Bryant's avatar
Bryant committed
181 182 183 184 185

  \param ticks Maximal number of major ticks.

  \sa scaleMaxMajor(), setScaleMaxMinor(),
      setScaleStepSize(), QwtScaleEngine::divideInterval()
pixhawk's avatar
pixhawk committed
186
*/
Bryant's avatar
Bryant committed
187
void QwtAbstractScale::setScaleMaxMajor( int ticks )
pixhawk's avatar
pixhawk committed
188
{
Bryant's avatar
Bryant committed
189 190
    if ( ticks != d_data->maxMajor )
    {
pixhawk's avatar
pixhawk committed
191 192 193 194 195
        d_data->maxMajor = ticks;
        updateScaleDraw();
    }
}

Bryant's avatar
Bryant committed
196 197 198 199 200 201 202 203 204
/*!
  \return Maximal number of major tick intervals
  \sa setScaleMaxMajor(), scaleMaxMinor()
*/
int QwtAbstractScale::scaleMaxMajor() const
{
    return d_data->maxMajor;
}

pixhawk's avatar
pixhawk committed
205 206 207 208 209 210
/*!
  \brief Set the maximum number of minor tick intervals

  The scale's minor ticks are calculated automatically such that
  the number of minor intervals does not exceed ticks.
  The default value is 3.
Bryant's avatar
Bryant committed
211 212 213 214 215

  \param ticks Maximal number of minor ticks.

  \sa scaleMaxMajor(), setScaleMaxMinor(),
      setScaleStepSize(), QwtScaleEngine::divideInterval()
pixhawk's avatar
pixhawk committed
216
*/
Bryant's avatar
Bryant committed
217
void QwtAbstractScale::setScaleMaxMinor( int ticks )
pixhawk's avatar
pixhawk committed
218
{
Bryant's avatar
Bryant committed
219 220
    if ( ticks != d_data->maxMinor )
    {
pixhawk's avatar
pixhawk committed
221 222 223 224 225
        d_data->maxMinor = ticks;
        updateScaleDraw();
    }
}

226
/*!
Bryant's avatar
Bryant committed
227 228
  \return Maximal number of minor tick intervals
  \sa setScaleMaxMinor(), scaleMaxMajor()
pixhawk's avatar
pixhawk committed
229
*/
230
int QwtAbstractScale::scaleMaxMinor() const
pixhawk's avatar
pixhawk committed
231 232 233 234
{
    return d_data->maxMinor;
}

235
/*!
Bryant's avatar
Bryant committed
236 237 238 239 240 241 242 243 244 245 246 247
   \brief Set the step size used for calculating a scale division

   The step size is hint for calculating the intervals for
   the major ticks of the scale. A value of 0.0 is interpreted
   as no hint.

   \param stepSize Hint for the step size of the scale

   \sa scaleStepSize(), QwtScaleEngine::divideScale()

   \note Position and distance between the major ticks also
         depends on scaleMaxMajor().
pixhawk's avatar
pixhawk committed
248
*/
Bryant's avatar
Bryant committed
249
void QwtAbstractScale::setScaleStepSize( double stepSize )
pixhawk's avatar
pixhawk committed
250
{
Bryant's avatar
Bryant committed
251 252 253 254 255 256 257 258 259 260 261 262 263 264
    if ( stepSize != d_data->stepSize )
    {
        d_data->stepSize = stepSize;
        updateScaleDraw();
    }
}

/*!
  \return Hint for the step size of the scale
  \sa setScaleStepSize(), QwtScaleEngine::divideScale()
*/
double QwtAbstractScale::scaleStepSize() const
{
    return d_data->stepSize;
pixhawk's avatar
pixhawk committed
265 266 267 268 269 270
}

/*!
  \brief Set a scale draw

  scaleDraw has to be created with new and will be deleted in
Bryant's avatar
Bryant committed
271 272 273
  the destructor or the next call of setAbstractScaleDraw().

  \sa abstractScaleDraw()
pixhawk's avatar
pixhawk committed
274
*/
Bryant's avatar
Bryant committed
275
void QwtAbstractScale::setAbstractScaleDraw( QwtAbstractScaleDraw *scaleDraw )
pixhawk's avatar
pixhawk committed
276 277 278 279 280
{
    if ( scaleDraw == NULL || scaleDraw == d_data->scaleDraw )
        return;

    if ( d_data->scaleDraw != NULL )
Bryant's avatar
Bryant committed
281
        scaleDraw->setScaleDiv( d_data->scaleDraw->scaleDiv() );
pixhawk's avatar
pixhawk committed
282 283 284

    delete d_data->scaleDraw;
    d_data->scaleDraw = scaleDraw;
285
}
pixhawk's avatar
pixhawk committed
286 287 288 289 290

/*!
    \return Scale draw
    \sa setAbstractScaleDraw()
*/
291
QwtAbstractScaleDraw *QwtAbstractScale::abstractScaleDraw()
pixhawk's avatar
pixhawk committed
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
{
    return d_data->scaleDraw;
}

/*!
    \return Scale draw
    \sa setAbstractScaleDraw()
*/
const QwtAbstractScaleDraw *QwtAbstractScale::abstractScaleDraw() const
{
    return d_data->scaleDraw;
}

/*!
  \brief Set a scale engine

Bryant's avatar
Bryant committed
308 309
  The scale engine is responsible for calculating the scale division
  and provides a transformation between scale and widget coordinates.
pixhawk's avatar
pixhawk committed
310 311

  scaleEngine has to be created with new and will be deleted in
Bryant's avatar
Bryant committed
312
  the destructor or the next call of setScaleEngine.
pixhawk's avatar
pixhawk committed
313
*/
Bryant's avatar
Bryant committed
314
void QwtAbstractScale::setScaleEngine( QwtScaleEngine *scaleEngine )
pixhawk's avatar
pixhawk committed
315
{
Bryant's avatar
Bryant committed
316 317
    if ( scaleEngine != NULL && scaleEngine != d_data->scaleEngine )
    {
pixhawk's avatar
pixhawk committed
318 319 320 321 322 323
        delete d_data->scaleEngine;
        d_data->scaleEngine = scaleEngine;
    }
}

/*!
Bryant's avatar
Bryant committed
324 325
  \return Scale engine
  \sa setScaleEngine()
pixhawk's avatar
pixhawk committed
326 327 328 329 330 331 332
*/
const QwtScaleEngine *QwtAbstractScale::scaleEngine() const
{
    return d_data->scaleEngine;
}

/*!
Bryant's avatar
Bryant committed
333 334
  \return Scale engine
  \sa setScaleEngine()
pixhawk's avatar
pixhawk committed
335 336 337 338 339 340 341
*/
QwtScaleEngine *QwtAbstractScale::scaleEngine()
{
    return d_data->scaleEngine;
}

/*!
Bryant's avatar
Bryant committed
342
  \return Scale boundaries and positions of the ticks
pixhawk's avatar
pixhawk committed
343

Bryant's avatar
Bryant committed
344 345 346 347
  The scale division might have been assigned explicitly
  or calculated implicitly by rescale(). 
 */
const QwtScaleDiv &QwtAbstractScale::scaleDiv() const
pixhawk's avatar
pixhawk committed
348
{
Bryant's avatar
Bryant committed
349
    return d_data->scaleDraw->scaleDiv();
pixhawk's avatar
pixhawk committed
350 351 352
}

/*!
Bryant's avatar
Bryant committed
353 354
  \return Map to translate between scale and widget coordinates
 */
pixhawk's avatar
pixhawk committed
355 356 357 358
const QwtScaleMap &QwtAbstractScale::scaleMap() const
{
    return d_data->scaleDraw->scaleMap();
}
Bryant's avatar
Bryant committed
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449

/*!
  Translate a scale value into a widget coordinate

  \param value Scale value 
  \return Corresponding widget coordinate for value
  \sa scaleMap(), invTransform()
 */
int QwtAbstractScale::transform( double value ) const
{
    return qRound( d_data->scaleDraw->scaleMap().transform( value ) );
}

/*!
  Translate a widget coordinate into a scale value

  \param value Widget coordinate
  \return Corresponding scale coordinate for value
  \sa scaleMap(), transform()
 */
double QwtAbstractScale::invTransform( int value ) const
{
    return d_data->scaleDraw->scaleMap().invTransform( value );
}

/*!
  \return True, when the scale is increasing in opposite direction
          to the widget coordinates
 */
bool QwtAbstractScale::isInverted() const
{
    return d_data->scaleDraw->scaleMap().isInverting();
}

/*!
  \return The boundary with the smaller value
  \sa maximum(), lowerBound(), upperBound()
 */
double QwtAbstractScale::minimum() const
{
    return qMin( d_data->scaleDraw->scaleDiv().lowerBound(),
        d_data->scaleDraw->scaleDiv().upperBound() );
}

/*!
  \return The boundary with the larger value
  \sa minimum(), lowerBound(), upperBound()
 */
double QwtAbstractScale::maximum() const
{
    return qMax( d_data->scaleDraw->scaleDiv().lowerBound(),
        d_data->scaleDraw->scaleDiv().upperBound() );
}

//! Notify changed scale
void QwtAbstractScale::scaleChange()
{
}

/*!
  Recalculate the scale division and update the scale.

  \param lowerBound Lower limit of the scale interval
  \param upperBound Upper limit of the scale interval
  \param stepSize Major step size

  \sa scaleChange()
*/
void QwtAbstractScale::rescale( 
    double lowerBound, double upperBound, double stepSize )
{
    const QwtScaleDiv scaleDiv = d_data->scaleEngine->divideScale(
        lowerBound, upperBound, d_data->maxMajor, d_data->maxMinor, stepSize );

    if ( scaleDiv != d_data->scaleDraw->scaleDiv() )
    {
#if 1
        d_data->scaleDraw->setTransformation(
            d_data->scaleEngine->transformation() );
#endif

        d_data->scaleDraw->setScaleDiv( scaleDiv );
        scaleChange();
    }
}

void QwtAbstractScale::updateScaleDraw()
{
    rescale( d_data->scaleDraw->scaleDiv().lowerBound(),
        d_data->scaleDraw->scaleDiv().upperBound(), d_data->stepSize );
}