Skip to content
qwt_scale_widget.cpp 22.1 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
 *
 * 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_scale_widget.h"
pixhawk's avatar
pixhawk committed
#include "qwt_painter.h"
#include "qwt_color_map.h"
#include "qwt_scale_map.h"
#include "qwt_math.h"
#include "qwt_scale_div.h"
#include "qwt_text.h"
Bryant's avatar
Bryant committed
#include "qwt_scale_engine.h"
#include <qpainter.h>
#include <qevent.h>
#include <qmath.h>
#include <qstyle.h>
#include <qstyleoption.h>
pixhawk's avatar
pixhawk committed

class QwtScaleWidget::PrivateData
{
public:
    PrivateData():
Bryant's avatar
Bryant committed
        scaleDraw( NULL )
    {
pixhawk's avatar
pixhawk committed
        colorBar.colorMap = NULL;
    }

Bryant's avatar
Bryant committed
    ~PrivateData()
    {
pixhawk's avatar
pixhawk committed
        delete scaleDraw;
        delete colorBar.colorMap;
    }

    QwtScaleDraw *scaleDraw;

    int borderDist[2];
    int minBorderDist[2];
    int scaleLength;
    int margin;

    int titleOffset;
    int spacing;
    QwtText title;

Bryant's avatar
Bryant committed
    QwtScaleWidget::LayoutFlags layoutFlags;

    struct t_colorBar
    {
pixhawk's avatar
pixhawk committed
        bool isEnabled;
        int width;
Bryant's avatar
Bryant committed
        QwtInterval interval;
pixhawk's avatar
pixhawk committed
        QwtColorMap *colorMap;
    } colorBar;
};

/*!
  \brief Create a scale with the position QwtScaleWidget::Left
  \param parent Parent widget
*/
Bryant's avatar
Bryant committed
QwtScaleWidget::QwtScaleWidget( QWidget *parent ):
    QWidget( parent )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    initScale( QwtScaleDraw::LeftScale );
pixhawk's avatar
pixhawk committed
}

/*!
  \brief Constructor
  \param align Alignment.
pixhawk's avatar
pixhawk committed
  \param parent Parent widget
*/
QwtScaleWidget::QwtScaleWidget(
Bryant's avatar
Bryant committed
        QwtScaleDraw::Alignment align, QWidget *parent ):
    QWidget( parent )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    initScale( align );
pixhawk's avatar
pixhawk committed
}

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

//! Initialize the scale
Bryant's avatar
Bryant committed
void QwtScaleWidget::initScale( QwtScaleDraw::Alignment align )
pixhawk's avatar
pixhawk committed
{
    d_data = new PrivateData;

Bryant's avatar
Bryant committed
    d_data->layoutFlags = 0;
    if ( align == QwtScaleDraw::RightScale )
        d_data->layoutFlags |= TitleInverted;
pixhawk's avatar
pixhawk committed

    d_data->borderDist[0] = 0;
    d_data->borderDist[1] = 0;
    d_data->minBorderDist[0] = 0;
    d_data->minBorderDist[1] = 0;
    d_data->margin = 4;
    d_data->titleOffset = 0;
    d_data->spacing = 2;

    d_data->scaleDraw = new QwtScaleDraw;
Bryant's avatar
Bryant committed
    d_data->scaleDraw->setAlignment( align );
    d_data->scaleDraw->setLength( 10 );

    d_data->scaleDraw->setScaleDiv(
        QwtLinearScaleEngine().divideScale( 0.0, 100.0, 10, 5 ) );
pixhawk's avatar
pixhawk committed

    d_data->colorBar.colorMap = new QwtLinearColorMap();
    d_data->colorBar.isEnabled = false;
    d_data->colorBar.width = 10;
pixhawk's avatar
pixhawk committed
    const int flags = Qt::AlignHCenter
Bryant's avatar
Bryant committed
        | Qt::TextExpandTabs | Qt::TextWordWrap;
    d_data->title.setRenderFlags( flags );
    d_data->title.setFont( font() );

    QSizePolicy policy( QSizePolicy::MinimumExpanding,
        QSizePolicy::Fixed );
pixhawk's avatar
pixhawk committed
    if ( d_data->scaleDraw->orientation() == Qt::Vertical )
        policy.transpose();

Bryant's avatar
Bryant committed
    setSizePolicy( policy );

    setAttribute( Qt::WA_WState_OwnSizePolicy, false );
}

/*!
   Toggle an layout flag

   \param flag Layout flag
   \param on true/false

   \sa testLayoutFlag(), LayoutFlag
*/
void QwtScaleWidget::setLayoutFlag( LayoutFlag flag, bool on )
{
    if ( ( ( d_data->layoutFlags & flag ) != 0 ) != on )
    {
        if ( on )
            d_data->layoutFlags |= flag;
        else
            d_data->layoutFlags &= ~flag;
    }
}
Bryant's avatar
Bryant committed
/*!
   Test a layout flag
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
   \param flag Layout flag
   \return true/false
   \sa setLayoutFlag(), LayoutFlag
*/
bool QwtScaleWidget::testLayoutFlag( LayoutFlag flag ) const
{
    return ( d_data->layoutFlags & flag );
pixhawk's avatar
pixhawk committed
}

Bryant's avatar
Bryant committed
/*!
  Give title new text contents

  \param title New title
  \sa title(), setTitle(const QwtText &);
*/
void QwtScaleWidget::setTitle( const QString &title )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( d_data->title.text() != title )
    {
        d_data->title.setText( title );
pixhawk's avatar
pixhawk committed
        layoutScale();
    }
}

/*!
Bryant's avatar
Bryant committed
  Give title new text contents

pixhawk's avatar
pixhawk committed
  \param title New title
Bryant's avatar
Bryant committed
  \sa title()
pixhawk's avatar
pixhawk committed
  \warning The title flags are interpreted in
               direction of the label, AlignTop, AlignBottom can't be set
               as the title will always be aligned to the scale.
*/
Bryant's avatar
Bryant committed
void QwtScaleWidget::setTitle( const QwtText &title )
pixhawk's avatar
pixhawk committed
{
    QwtText t = title;
Bryant's avatar
Bryant committed
    const int flags = title.renderFlags() & ~( Qt::AlignTop | Qt::AlignBottom );
    t.setRenderFlags( flags );
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
    if ( t != d_data->title )
    {
pixhawk's avatar
pixhawk committed
        d_data->title = t;
        layoutScale();
    }
}

/*!
  Change the alignment

  \param alignment New alignment
Bryant's avatar
Bryant committed
  \sa alignment()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtScaleWidget::setAlignment( QwtScaleDraw::Alignment alignment )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( d_data->scaleDraw )
        d_data->scaleDraw->setAlignment( alignment );

    if ( !testAttribute( Qt::WA_WState_OwnSizePolicy ) )
pixhawk's avatar
pixhawk committed
    {
Bryant's avatar
Bryant committed
        QSizePolicy policy( QSizePolicy::MinimumExpanding,
            QSizePolicy::Fixed );
pixhawk's avatar
pixhawk committed
        if ( d_data->scaleDraw->orientation() == Qt::Vertical )
            policy.transpose();

Bryant's avatar
Bryant committed
        setSizePolicy( policy );

        setAttribute( Qt::WA_WState_OwnSizePolicy, false );
pixhawk's avatar
pixhawk committed
    }

    layoutScale();
}


/*!
    \return position
Bryant's avatar
Bryant committed
    \sa setPosition()
pixhawk's avatar
pixhawk committed
*/
QwtScaleDraw::Alignment QwtScaleWidget::alignment() const
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( !scaleDraw() )
pixhawk's avatar
pixhawk committed
        return QwtScaleDraw::LeftScale;

    return scaleDraw()->alignment();
}

/*!
  Specify distances of the scale's endpoints from the
  widget's borders. The actual borders will never be less
  than minimum border distance.
  \param dist1 Left or top Distance
  \param dist2 Right or bottom distance
Bryant's avatar
Bryant committed
  \sa borderDist()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtScaleWidget::setBorderDist( int dist1, int dist2 )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( dist1 != d_data->borderDist[0] || dist2 != d_data->borderDist[1] )
    {
pixhawk's avatar
pixhawk committed
        d_data->borderDist[0] = dist1;
        d_data->borderDist[1] = dist2;
        layoutScale();
    }
}

/*!
  \brief Specify the margin to the colorBar/base line.
  \param margin Margin
Bryant's avatar
Bryant committed
  \sa margin()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtScaleWidget::setMargin( int margin )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    margin = qMax( 0, margin );
    if ( margin != d_data->margin )
    {
pixhawk's avatar
pixhawk committed
        d_data->margin = margin;
        layoutScale();
    }
}

/*!
  \brief Specify the distance between color bar, scale and title
  \param spacing Spacing
Bryant's avatar
Bryant committed
  \sa spacing()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtScaleWidget::setSpacing( int spacing )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    spacing = qMax( 0, spacing );
    if ( spacing != d_data->spacing )
    {
pixhawk's avatar
pixhawk committed
        d_data->spacing = spacing;
        layoutScale();
    }
}

/*!
  \brief Change the alignment for the labels.

Bryant's avatar
Bryant committed
  \sa QwtScaleDraw::setLabelAlignment(), setLabelRotation()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtScaleWidget::setLabelAlignment( Qt::Alignment alignment )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    d_data->scaleDraw->setLabelAlignment( alignment );
pixhawk's avatar
pixhawk committed
    layoutScale();
}

/*!
  \brief Change the rotation for the labels.
  See QwtScaleDraw::setLabelRotation().
Bryant's avatar
Bryant committed

  \param rotation Rotation
  \sa QwtScaleDraw::setLabelRotation(), setLabelFlags()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtScaleWidget::setLabelRotation( double rotation )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    d_data->scaleDraw->setLabelRotation( rotation );
pixhawk's avatar
pixhawk committed
    layoutScale();
}

/*!
Bryant's avatar
Bryant committed
  Set a scale draw

  scaleDraw has to be created with new and will be deleted in
  ~QwtScaleWidget() or the next call of setScaleDraw().
  scaleDraw will be initialized with the attributes of
  the previous scaleDraw object.

  \param scaleDraw ScaleDraw object
  \sa scaleDraw()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtScaleWidget::setScaleDraw( QwtScaleDraw *scaleDraw )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( ( scaleDraw == NULL ) || ( scaleDraw == d_data->scaleDraw ) )
pixhawk's avatar
pixhawk committed
        return;

Bryant's avatar
Bryant committed
    const QwtScaleDraw* sd = d_data->scaleDraw;
    if ( sd )
    {
        scaleDraw->setAlignment( sd->alignment() );
        scaleDraw->setScaleDiv( sd->scaleDiv() );

        QwtTransform *transform = NULL;
        if ( sd->scaleMap().transformation() )
            transform = sd->scaleMap().transformation()->copy();

        scaleDraw->setTransformation( transform );
    }
pixhawk's avatar
pixhawk committed

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

    layoutScale();
}

Bryant's avatar
Bryant committed
    \return scaleDraw of this scale
    \sa setScaleDraw(), QwtScaleDraw::setScaleDraw()
pixhawk's avatar
pixhawk committed
*/
const QwtScaleDraw *QwtScaleWidget::scaleDraw() const
{
    return d_data->scaleDraw;
pixhawk's avatar
pixhawk committed
}

Bryant's avatar
Bryant committed
    \return scaleDraw of this scale
    \sa QwtScaleDraw::setScaleDraw()
pixhawk's avatar
pixhawk committed
*/
QwtScaleDraw *QwtScaleWidget::scaleDraw()
{
    return d_data->scaleDraw;
pixhawk's avatar
pixhawk committed
}

/*!
    \return title
Bryant's avatar
Bryant committed
    \sa setTitle()
pixhawk's avatar
pixhawk committed
*/
QwtText QwtScaleWidget::title() const
pixhawk's avatar
pixhawk committed
{
    return d_data->title;
}

/*!
    \return start border distance
Bryant's avatar
Bryant committed
    \sa setBorderDist()
pixhawk's avatar
pixhawk committed
*/
int QwtScaleWidget::startBorderDist() const
{
    return d_data->borderDist[0];
}
pixhawk's avatar
pixhawk committed

/*!
    \return end border distance
Bryant's avatar
Bryant committed
    \sa setBorderDist()
pixhawk's avatar
pixhawk committed
*/
int QwtScaleWidget::endBorderDist() const
{
    return d_data->borderDist[1];
pixhawk's avatar
pixhawk committed
}

pixhawk's avatar
pixhawk committed
    \return margin
Bryant's avatar
Bryant committed
    \sa setMargin()
pixhawk's avatar
pixhawk committed
*/
int QwtScaleWidget::margin() const
{
    return d_data->margin;
pixhawk's avatar
pixhawk committed
}

pixhawk's avatar
pixhawk committed
    \return distance between scale and title
Bryant's avatar
Bryant committed
    \sa setMargin()
pixhawk's avatar
pixhawk committed
*/
int QwtScaleWidget::spacing() const
{
    return d_data->spacing;
pixhawk's avatar
pixhawk committed
}

Bryant's avatar
Bryant committed
  \brief paintEvent
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtScaleWidget::paintEvent( QPaintEvent *event )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    QPainter painter( this );
    painter.setClipRegion( event->region() );

    QStyleOption opt;
    opt.init(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);

    draw( &painter );
Bryant's avatar
Bryant committed

pixhawk's avatar
pixhawk committed
/*!
Bryant's avatar
Bryant committed
  \brief draw the scale
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtScaleWidget::draw( QPainter *painter ) const
{
    d_data->scaleDraw->draw( painter, palette() );

    if ( d_data->colorBar.isEnabled && d_data->colorBar.width > 0 &&
        d_data->colorBar.interval.isValid() )
    {
        drawColorBar( painter, colorBarRect( contentsRect() ) );
    }

    QRect r = contentsRect();
    if ( d_data->scaleDraw->orientation() == Qt::Horizontal )
    {
        r.setLeft( r.left() + d_data->borderDist[0] );
        r.setWidth( r.width() - d_data->borderDist[1] );
pixhawk's avatar
pixhawk committed
    }
Bryant's avatar
Bryant committed
    else
    {
        r.setTop( r.top() + d_data->borderDist[0] );
        r.setHeight( r.height() - d_data->borderDist[1] );
    }

    if ( !d_data->title.isEmpty() )
        drawTitle( painter, d_data->scaleDraw->alignment(), r );
pixhawk's avatar
pixhawk committed
}

/*!
Bryant's avatar
Bryant committed
  Calculate the the rectangle for the color bar

  \param rect Bounding rectangle for all components of the scale
  \return Rectangle for the color bar
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
QRectF QwtScaleWidget::colorBarRect( const QRectF& rect ) const
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    QRectF cr = rect;
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
    if ( d_data->scaleDraw->orientation() == Qt::Horizontal )
    {
        cr.setLeft( cr.left() + d_data->borderDist[0] );
        cr.setWidth( cr.width() - d_data->borderDist[1] + 1 );
pixhawk's avatar
pixhawk committed
    }
Bryant's avatar
Bryant committed
    else
    {
        cr.setTop( cr.top() + d_data->borderDist[0] );
        cr.setHeight( cr.height() - d_data->borderDist[1] + 1 );
pixhawk's avatar
pixhawk committed
    }

Bryant's avatar
Bryant committed
    switch ( d_data->scaleDraw->alignment() )
    {
        case QwtScaleDraw::LeftScale:
Bryant's avatar
Bryant committed
        {
            cr.setLeft( cr.right() - d_data->margin
                - d_data->colorBar.width );
            cr.setWidth( d_data->colorBar.width );
Bryant's avatar
Bryant committed
        }

        case QwtScaleDraw::RightScale:
Bryant's avatar
Bryant committed
        {
            cr.setLeft( cr.left() + d_data->margin );
            cr.setWidth( d_data->colorBar.width );
Bryant's avatar
Bryant committed
        }

        case QwtScaleDraw::BottomScale:
Bryant's avatar
Bryant committed
        {
            cr.setTop( cr.top() + d_data->margin );
            cr.setHeight( d_data->colorBar.width );
Bryant's avatar
Bryant committed
        }

        case QwtScaleDraw::TopScale:
Bryant's avatar
Bryant committed
        {
            cr.setTop( cr.bottom() - d_data->margin
                - d_data->colorBar.width );
            cr.setHeight( d_data->colorBar.width );
pixhawk's avatar
pixhawk committed
        }
    }

    return cr;
}

/*!
Bryant's avatar
Bryant committed
  Event handler for resize events
  \param event Resize event
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtScaleWidget::resizeEvent( QResizeEvent *event )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    Q_UNUSED( event );
    layoutScale( false );
pixhawk's avatar
pixhawk committed
}

Bryant's avatar
Bryant committed
/*!
  Recalculate the scale's geometry and layout based on
  the current geometry and fonts.

  \param update_geometry Notify the layout system and call update
                         to redraw the scale
*/
pixhawk's avatar
pixhawk committed

void QwtScaleWidget::layoutScale( bool update_geometry )
{
    int bd0, bd1;
Bryant's avatar
Bryant committed
    getBorderDistHint( bd0, bd1 );
pixhawk's avatar
pixhawk committed
    if ( d_data->borderDist[0] > bd0 )
        bd0 = d_data->borderDist[0];
    if ( d_data->borderDist[1] > bd1 )
        bd1 = d_data->borderDist[1];

    int colorBarWidth = 0;
    if ( d_data->colorBar.isEnabled && d_data->colorBar.interval.isValid() )
        colorBarWidth = d_data->colorBar.width + d_data->spacing;

Bryant's avatar
Bryant committed
    const QRectF r = contentsRect();
    double x, y, length;
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
    if ( d_data->scaleDraw->orientation() == Qt::Vertical )
    {
pixhawk's avatar
pixhawk committed
        y = r.top() + bd0;
Bryant's avatar
Bryant committed
        length = r.height() - ( bd0 + bd1 );
pixhawk's avatar
pixhawk committed

        if ( d_data->scaleDraw->alignment() == QwtScaleDraw::LeftScale )
Bryant's avatar
Bryant committed
            x = r.right() - 1.0 - d_data->margin - colorBarWidth;
pixhawk's avatar
pixhawk committed
        else
            x = r.left() + d_data->margin + colorBarWidth;
Bryant's avatar
Bryant committed
    }
    else
    {
        x = r.left() + bd0;
Bryant's avatar
Bryant committed
        length = r.width() - ( bd0 + bd1 );
pixhawk's avatar
pixhawk committed

        if ( d_data->scaleDraw->alignment() == QwtScaleDraw::BottomScale )
            y = r.top() + d_data->margin + colorBarWidth;
        else
Bryant's avatar
Bryant committed
            y = r.bottom() - 1.0 - d_data->margin - colorBarWidth;
pixhawk's avatar
pixhawk committed
    }

Bryant's avatar
Bryant committed
    d_data->scaleDraw->move( x, y );
    d_data->scaleDraw->setLength( length );
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
    const int extent = qCeil( d_data->scaleDraw->extent( font() ) );
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
    d_data->titleOffset =
        d_data->margin + d_data->spacing + colorBarWidth + extent;

    if ( update_geometry )
    {
        updateGeometry();
        update();
pixhawk's avatar
pixhawk committed
    }
}

Bryant's avatar
Bryant committed
/*!
  Draw the color bar of the scale widget

  \param painter Painter
  \param rect Bounding rectangle for the color bar

  \sa setColorBarEnabled()
*/
void QwtScaleWidget::drawColorBar( QPainter *painter, const QRectF& rect ) const
pixhawk's avatar
pixhawk committed
{
    if ( !d_data->colorBar.interval.isValid() )
        return;

    const QwtScaleDraw* sd = d_data->scaleDraw;

Bryant's avatar
Bryant committed
    QwtPainter::drawColorBar( painter, *d_data->colorBar.colorMap,
        d_data->colorBar.interval.normalized(), sd->scaleMap(),
        sd->orientation(), rect );
pixhawk's avatar
pixhawk committed
}

/*!
  Rotate and paint a title according to its position into a given rectangle.
Bryant's avatar
Bryant committed

pixhawk's avatar
pixhawk committed
  \param painter Painter
  \param align Alignment
  \param rect Bounding rectangle
*/

Bryant's avatar
Bryant committed
void QwtScaleWidget::drawTitle( QPainter *painter,
    QwtScaleDraw::Alignment align, const QRectF &rect ) const
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    QRectF r = rect;
pixhawk's avatar
pixhawk committed
    double angle;
    int flags = d_data->title.renderFlags() &
Bryant's avatar
Bryant committed
        ~( Qt::AlignTop | Qt::AlignBottom | Qt::AlignVCenter );

    switch ( align )
    {
        case QwtScaleDraw::LeftScale:
            angle = -90.0;
            flags |= Qt::AlignTop;
            r.setRect( r.left(), r.bottom(),
                r.height(), r.width() - d_data->titleOffset );
            break;

        case QwtScaleDraw::RightScale:
            angle = -90.0;
            flags |= Qt::AlignTop;
            r.setRect( r.left() + d_data->titleOffset, r.bottom(),
                r.height(), r.width() - d_data->titleOffset );
            break;

        case QwtScaleDraw::BottomScale:
            angle = 0.0;
            flags |= Qt::AlignBottom;
            r.setTop( r.top() + d_data->titleOffset );
            break;

        case QwtScaleDraw::TopScale:
        default:
            angle = 0.0;
            flags |= Qt::AlignTop;
            r.setBottom( r.bottom() - d_data->titleOffset );
            break;
    }

    if ( d_data->layoutFlags & TitleInverted )
    {
        if ( align == QwtScaleDraw::LeftScale
            || align == QwtScaleDraw::RightScale )
        {
            angle = -angle;
            r.setRect( r.x() + r.height(), r.y() - r.width(),
                r.width(), r.height() );
        }
pixhawk's avatar
pixhawk committed
    }

    painter->save();
Bryant's avatar
Bryant committed
    painter->setFont( font() );
    painter->setPen( palette().color( QPalette::Text ) );
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
    painter->translate( r.x(), r.y() );
    if ( angle != 0.0 )
        painter->rotate( angle );
pixhawk's avatar
pixhawk committed

    QwtText title = d_data->title;
Bryant's avatar
Bryant committed
    title.setRenderFlags( flags );
    title.draw( painter, QRectF( 0.0, 0.0, r.width(), r.height() ) );
pixhawk's avatar
pixhawk committed

    painter->restore();
}

/*!
  \brief Notify a change of the scale

  This virtual function can be overloaded by derived
  classes. The default implementation updates the geometry
  and repaints the widget.
*/

void QwtScaleWidget::scaleChange()
{
    layoutScale();
}

/*!
  \return a size hint
*/
QSize QwtScaleWidget::sizeHint() const
{
    return minimumSizeHint();
}

/*!
  \return a minimum size hint
*/
QSize QwtScaleWidget::minimumSizeHint() const
{
    const Qt::Orientation o = d_data->scaleDraw->orientation();

    // Border Distance cannot be less than the scale borderDistHint
    // Note, the borderDistHint is already included in minHeight/minWidth
    int length = 0;
    int mbd1, mbd2;
Bryant's avatar
Bryant committed
    getBorderDistHint( mbd1, mbd2 );
    length += qMax( 0, d_data->borderDist[0] - mbd1 );
    length += qMax( 0, d_data->borderDist[1] - mbd2 );
    length += d_data->scaleDraw->minLength( font() );

    int dim = dimForLength( length, font() );
    if ( length < dim )
    {
pixhawk's avatar
pixhawk committed
        // compensate for long titles
        length = dim;
Bryant's avatar
Bryant committed
        dim = dimForLength( length, font() );
pixhawk's avatar
pixhawk committed
    }

Bryant's avatar
Bryant committed
    QSize size( length + 2, dim );
pixhawk's avatar
pixhawk committed
    if ( o == Qt::Vertical )
        size.transpose();

Bryant's avatar
Bryant committed
    int left, right, top, bottom;
    getContentsMargins( &left, &top, &right, &bottom );
    return size + QSize( left + right, top + bottom );
pixhawk's avatar
pixhawk committed
}

/*!
  \brief Find the height of the title for a given width.
  \param width Width
  \return height Height
 */

Bryant's avatar
Bryant committed
int QwtScaleWidget::titleHeightForWidth( int width ) const
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    return qCeil( d_data->title.heightForWidth( width, font() ) );
pixhawk's avatar
pixhawk committed
}

/*!
  \brief Find the minimum dimension for a given length.
         dim is the height, length the width seen in
         direction of the title.
  \param length width for horizontal, height for vertical scales
  \param scaleFont Font of the scale
  \return height for horizontal, width for vertical scales
*/

Bryant's avatar
Bryant committed
int QwtScaleWidget::dimForLength( int length, const QFont &scaleFont ) const
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    const int extent = qCeil( d_data->scaleDraw->extent( scaleFont ) );

    int dim = d_data->margin + extent + 1;
pixhawk's avatar
pixhawk committed

    if ( !d_data->title.isEmpty() )
Bryant's avatar
Bryant committed
        dim += titleHeightForWidth( length ) + d_data->spacing;
pixhawk's avatar
pixhawk committed

    if ( d_data->colorBar.isEnabled && d_data->colorBar.interval.isValid() )
        dim += d_data->colorBar.width + d_data->spacing;

    return dim;
}

/*!
  \brief Calculate a hint for the border distances.

  This member function calculates the distance
  of the scale's endpoints from the widget borders which
  is required for the mark labels to fit into the widget.
  The maximum of this distance an the minimum border distance
  is returned.

Bryant's avatar
Bryant committed
  \param start Return parameter for the border width at 
               the beginning of the scale
  \param end Return parameter for the border width at the 
             end of the scale

pixhawk's avatar
pixhawk committed
  \warning
  <ul> <li>The minimum border distance depends on the font.</ul>
  \sa setMinBorderDist(), getMinBorderDist(), setBorderDist()
*/
Bryant's avatar
Bryant committed
void QwtScaleWidget::getBorderDistHint( int &start, int &end ) const
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    d_data->scaleDraw->getBorderDistHint( font(), start, end );
pixhawk's avatar
pixhawk committed

    if ( start < d_data->minBorderDist[0] )
        start = d_data->minBorderDist[0];

    if ( end < d_data->minBorderDist[1] )
        end = d_data->minBorderDist[1];
}

/*!
  Set a minimum value for the distances of the scale's endpoints from
pixhawk's avatar
pixhawk committed
  the widget borders. This is useful to avoid that the scales
  are "jumping", when the tick labels or their positions change
pixhawk's avatar
pixhawk committed
  often.

Bryant's avatar
Bryant committed
  \param start Minimum for the start border
  \param end Minimum for the end border
pixhawk's avatar
pixhawk committed
  \sa getMinBorderDist(), getBorderDistHint()
*/
Bryant's avatar
Bryant committed
void QwtScaleWidget::setMinBorderDist( int start, int end )
pixhawk's avatar
pixhawk committed
{
    d_data->minBorderDist[0] = start;
    d_data->minBorderDist[1] = end;
}

/*!
  Get the minimum value for the distances of the scale's endpoints from
pixhawk's avatar
pixhawk committed
  the widget borders.

Bryant's avatar
Bryant committed
  \param start Return parameter for the border width at 
               the beginning of the scale
  \param end Return parameter for the border width at the 
             end of the scale

pixhawk's avatar
pixhawk committed
  \sa setMinBorderDist(), getBorderDistHint()
*/
Bryant's avatar
Bryant committed
void QwtScaleWidget::getMinBorderDist( int &start, int &end ) const
pixhawk's avatar
pixhawk committed
{
    start = d_data->minBorderDist[0];
    end = d_data->minBorderDist[1];
}

/*!
  \brief Assign a scale division

  The scale division determines where to set the tick marks.

  \param scaleDiv Scale Division
  \sa For more information about scale divisions, see QwtScaleDiv.
*/
Bryant's avatar
Bryant committed
void QwtScaleWidget::setScaleDiv( const QwtScaleDiv &scaleDiv )
pixhawk's avatar
pixhawk committed
{
    QwtScaleDraw *sd = d_data->scaleDraw;
Bryant's avatar
Bryant committed
    if ( sd->scaleDiv() != scaleDiv )
    {
        sd->setScaleDiv( scaleDiv );
pixhawk's avatar
pixhawk committed
        layoutScale();

Bryant's avatar
Bryant committed
        Q_EMIT scaleDivChanged();
    }
pixhawk's avatar
pixhawk committed
}

Bryant's avatar
Bryant committed
/*!
  Set the transformation

  \param transformation Transformation
  \sa QwtAbstractScaleDraw::scaleDraw(), QwtScaleMap
 */
void QwtScaleWidget::setTransformation( QwtTransform *transformation )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    d_data->scaleDraw->setTransformation( transformation );
    layoutScale();
}

/*!
  En/disable a color bar associated to the scale
  \sa isColorBarEnabled(), setColorBarWidth()
*/
void QwtScaleWidget::setColorBarEnabled( bool on )
{
    if ( on != d_data->colorBar.isEnabled )
    {
pixhawk's avatar
pixhawk committed
        d_data->colorBar.isEnabled = on;
        layoutScale();
    }
}

Bryant's avatar
Bryant committed
/*!
  \return true, when the color bar is enabled
  \sa setColorBarEnabled(), setColorBarWidth()
*/
pixhawk's avatar
pixhawk committed
bool QwtScaleWidget::isColorBarEnabled() const
{
    return d_data->colorBar.isEnabled;
}

Bryant's avatar
Bryant committed
/*!
  Set the width of the color bar
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
  \param width Width
  \sa colorBarWidth(), setColorBarEnabled()
*/
void QwtScaleWidget::setColorBarWidth( int width )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( width != d_data->colorBar.width )
    {
pixhawk's avatar
pixhawk committed
        d_data->colorBar.width = width;
        if ( isColorBarEnabled() )
            layoutScale();
    }
}

Bryant's avatar
Bryant committed
/*!
  \return Width of the color bar
  \sa setColorBarEnabled(), setColorBarEnabled()
*/
pixhawk's avatar
pixhawk committed
int QwtScaleWidget::colorBarWidth() const
{
    return d_data->colorBar.width;
}

Bryant's avatar
Bryant committed
/*!
  \return Value interval for the color bar
  \sa setColorMap(), colorMap()
*/
QwtInterval QwtScaleWidget::colorBarInterval() const
pixhawk's avatar
pixhawk committed
{
    return d_data->colorBar.interval;
}

Bryant's avatar
Bryant committed
/*!
  Set the color map and value interval, that are used for displaying
  the color bar.

  \param interval Value interval
  \param colorMap Color map

  \sa colorMap(), colorBarInterval()
*/
void QwtScaleWidget::setColorMap(
    const QwtInterval &interval, QwtColorMap *colorMap )
pixhawk's avatar
pixhawk committed
{
    d_data->colorBar.interval = interval;

Bryant's avatar
Bryant committed
    if ( colorMap != d_data->colorBar.colorMap )
    {
        delete d_data->colorBar.colorMap;
        d_data->colorBar.colorMap = colorMap;
    }
pixhawk's avatar
pixhawk committed

    if ( isColorBarEnabled() )
        layoutScale();
}

Bryant's avatar
Bryant committed
/*!
  \return Color map
  \sa setColorMap(), colorBarInterval()
*/
const QwtColorMap *QwtScaleWidget::colorMap() const
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    return d_data->colorBar.colorMap;
pixhawk's avatar
pixhawk committed
}