Skip to content
qwt_abstract_scale.cpp 10.2 KiB
Newer Older
pixhawk's avatar
pixhawk committed
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 * Qwt Widget Library
 * Copyright (C) 1997   Josef Wilgen
 * Copyright (C) 2002   Uwe Rathmann
pixhawk's avatar
pixhawk committed
 * 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
#include "qwt_abstract_scale.h"
pixhawk's avatar
pixhawk committed
#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
#include "qwt_interval.h"
pixhawk's avatar
pixhawk committed

class QwtAbstractScale::PrivateData
{
public:
    PrivateData():
Bryant's avatar
Bryant committed
        maxMajor( 5 ),
        maxMinor( 3 ),
        stepSize( 0.0 )
    {
        scaleEngine = new QwtLinearScaleEngine();
pixhawk's avatar
pixhawk committed
        scaleDraw = new QwtScaleDraw();
    }

Bryant's avatar
Bryant committed
    ~PrivateData()
    {
pixhawk's avatar
pixhawk committed
        delete scaleEngine;
        delete scaleDraw;
    }

    QwtScaleEngine *scaleEngine;
    QwtAbstractScaleDraw *scaleDraw;

    int maxMajor;
    int maxMinor;
    double stepSize;
};

/*!
  Constructor

Bryant's avatar
Bryant committed
  \param parent Parent widget

  Creates a default QwtScaleDraw and a QwtLinearScaleEngine.
Bryant's avatar
Bryant committed
  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
*/
Bryant's avatar
Bryant committed
QwtAbstractScale::QwtAbstractScale( QWidget *parent ):
    QWidget( parent )
pixhawk's avatar
pixhawk committed
{
    d_data = new PrivateData;
Bryant's avatar
Bryant committed
    rescale( 0.0, 100.0, d_data->stepSize );
pixhawk's avatar
pixhawk committed
}

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

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

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

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

Bryant's avatar
Bryant committed
/*!
  \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
}

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

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

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

Bryant's avatar
Bryant committed
/*!
  \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

/*!
  \brief Specify a scale.

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

Bryant's avatar
Bryant committed
  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
*/
Bryant's avatar
Bryant committed
void QwtAbstractScale::setScale( double lowerBound, double upperBound )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    rescale( lowerBound, upperBound, d_data->stepSize );
pixhawk's avatar
pixhawk committed
}

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

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

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

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

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

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

  \param scaleDiv Scale division
  \sa setAutoScale()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtAbstractScale::setScale( const QwtScaleDiv &scaleDiv )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    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
        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

pixhawk's avatar
pixhawk committed
  The default value is 5.
Bryant's avatar
Bryant committed

  \param ticks Maximal number of major ticks.

  \sa scaleMaxMajor(), setScaleMaxMinor(),
      setScaleStepSize(), QwtScaleEngine::divideInterval()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtAbstractScale::setScaleMaxMajor( int ticks )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( ticks != d_data->maxMajor )
    {
pixhawk's avatar
pixhawk committed
        d_data->maxMajor = ticks;
        updateScaleDraw();
    }
}

Bryant's avatar
Bryant committed
/*!
  \return Maximal number of major tick intervals
  \sa setScaleMaxMajor(), scaleMaxMinor()
*/
int QwtAbstractScale::scaleMaxMajor() const
{
    return d_data->maxMajor;
}

pixhawk's avatar
pixhawk committed
/*!
  \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

  \param ticks Maximal number of minor ticks.

  \sa scaleMaxMajor(), setScaleMaxMinor(),
      setScaleStepSize(), QwtScaleEngine::divideInterval()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtAbstractScale::setScaleMaxMinor( int ticks )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( ticks != d_data->maxMinor )
    {
pixhawk's avatar
pixhawk committed
        d_data->maxMinor = ticks;
        updateScaleDraw();
    }
}

Bryant's avatar
Bryant committed
  \return Maximal number of minor tick intervals
  \sa setScaleMaxMinor(), scaleMaxMajor()
pixhawk's avatar
pixhawk committed
*/
int QwtAbstractScale::scaleMaxMinor() const
pixhawk's avatar
pixhawk committed
{
    return d_data->maxMinor;
}

Bryant's avatar
Bryant committed
   \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
*/
Bryant's avatar
Bryant committed
void QwtAbstractScale::setScaleStepSize( double stepSize )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    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
}

/*!
  \brief Set a scale draw

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

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

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

    delete d_data->scaleDraw;
    d_data->scaleDraw = scaleDraw;
pixhawk's avatar
pixhawk committed

/*!
    \return Scale draw
    \sa setAbstractScaleDraw()
*/
QwtAbstractScaleDraw *QwtAbstractScale::abstractScaleDraw()
pixhawk's avatar
pixhawk committed
{
    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
  The scale engine is responsible for calculating the scale division
  and provides a transformation between scale and widget coordinates.
pixhawk's avatar
pixhawk committed

  scaleEngine has to be created with new and will be deleted in
Bryant's avatar
Bryant committed
  the destructor or the next call of setScaleEngine.
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtAbstractScale::setScaleEngine( QwtScaleEngine *scaleEngine )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( scaleEngine != NULL && scaleEngine != d_data->scaleEngine )
    {
pixhawk's avatar
pixhawk committed
        delete d_data->scaleEngine;
        d_data->scaleEngine = scaleEngine;
    }
}

/*!
Bryant's avatar
Bryant committed
  \return Scale engine
  \sa setScaleEngine()
pixhawk's avatar
pixhawk committed
*/
const QwtScaleEngine *QwtAbstractScale::scaleEngine() const
{
    return d_data->scaleEngine;
}

/*!
Bryant's avatar
Bryant committed
  \return Scale engine
  \sa setScaleEngine()
pixhawk's avatar
pixhawk committed
*/
QwtScaleEngine *QwtAbstractScale::scaleEngine()
{
    return d_data->scaleEngine;
}

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

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

/*!
Bryant's avatar
Bryant committed
  \return Map to translate between scale and widget coordinates
 */
pixhawk's avatar
pixhawk committed
const QwtScaleMap &QwtAbstractScale::scaleMap() const
{
    return d_data->scaleDraw->scaleMap();
}
Bryant's avatar
Bryant committed

/*!
  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 );
}