Skip to content
Snippets Groups Projects
qwt_compass.cpp 7.23 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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_compass.h"
    #include "qwt_compass_rose.h"
    
    pixhawk's avatar
    pixhawk committed
    #include "qwt_math.h"
    #include "qwt_scale_draw.h"
    #include "qwt_painter.h"
    #include "qwt_dial_needle.h"
    
    Bryant's avatar
    Bryant committed
    #include <qpainter.h>
    #include <qpixmap.h>
    #include <qevent.h>
    
    /*! 
      \brief Constructor
    
      Initializes a label map for multiples of 45 degrees
     */
    QwtCompassScaleDraw::QwtCompassScaleDraw()
    {
        enableComponent( QwtAbstractScaleDraw::Backbone, false );
        enableComponent( QwtAbstractScaleDraw::Ticks, false );
    
        d_labelMap.insert( 0.0, QString::fromLatin1( "N" ) );
        d_labelMap.insert( 45.0, QString::fromLatin1( "NE" ) );
        d_labelMap.insert( 90.0, QString::fromLatin1( "E" ) );
        d_labelMap.insert( 135.0, QString::fromLatin1( "SE" ) );
        d_labelMap.insert( 180.0, QString::fromLatin1( "S" ) );
        d_labelMap.insert( 225.0, QString::fromLatin1( "SW" ) );
        d_labelMap.insert( 270.0, QString::fromLatin1( "W" ) );
        d_labelMap.insert( 315.0, QString::fromLatin1( "NW" ) );
    
    #if 0
        d_labelMap.insert( 22.5, QString::fromLatin1( "NNE" ) );
        d_labelMap.insert( 67.5, QString::fromLatin1( "NEE" ) );
        d_labelMap.insert( 112.5, QString::fromLatin1( "SEE" ) );
        d_labelMap.insert( 157.5, QString::fromLatin1( "SSE" ) );
        d_labelMap.insert( 202.5, QString::fromLatin1( "SSW" ) );
        d_labelMap.insert( 247.5, QString::fromLatin1( "SWW" ) );
        d_labelMap.insert( 292.5, QString::fromLatin1( "NWW" ) );
        d_labelMap.insert( 337.5, QString::fromLatin1( "NNW" ) );
    #endif
    }
    
    /*! 
      \brief Constructor
    
      \param map Value to label map
     */
    QwtCompassScaleDraw::QwtCompassScaleDraw( const QMap<double, QString> &map ):
        d_labelMap( map )
    {
        enableComponent( QwtAbstractScaleDraw::Backbone, false );
        enableComponent( QwtAbstractScaleDraw::Ticks, false );
    }
    
    /*!
      \brief Set a map, mapping values to labels
      \param map Value to label map
    
      The values of the major ticks are found by looking into this
      map. The default map consists of the labels N, NE, E, SE, S, SW, W, NW.
    
      \warning The map will have no effect for values that are no major
               tick values. Major ticks can be changed by QwtScaleDraw::setScale
    
      \sa labelMap(), scaleDraw(), setScale()
    */
    void QwtCompassScaleDraw::setLabelMap( const QMap<double, QString> &map )
    {
        d_labelMap = map;
    }
    
    
    /*!
      \return map, mapping values to labels
      \sa setLabelMap()
    */
    QMap<double, QString> QwtCompassScaleDraw::labelMap() const
    {
        return d_labelMap;
    }
    
    /*!
      Map a value to a corresponding label
    
      \param value Value that will be mapped
    
      label() looks in the labelMap() for a corresponding label for value
      or returns an null text.
    
      \return Label, or QString::null
      \sa labelMap(), setLabelMap()
    */
    
    QwtText QwtCompassScaleDraw::label( double value ) const
    {
        if ( qFuzzyCompare( value + 1.0, 1.0 ) )
            value = 0.0;
    
        if ( value < 0.0 )
            value += 360.0;
    
        if ( d_labelMap.contains( value ) )
            return d_labelMap[value];
    
        return QwtText();
    }
    
    pixhawk's avatar
    pixhawk committed
    
    class QwtCompass::PrivateData
    {
    public:
        PrivateData():
    
    Bryant's avatar
    Bryant committed
            rose( NULL )
        {
    
    pixhawk's avatar
    pixhawk committed
        }
    
    
    Bryant's avatar
    Bryant committed
        ~PrivateData()
        {
    
    pixhawk's avatar
    pixhawk committed
            delete rose;
        }
    
        QwtCompassRose *rose;
    };
    
    /*!
      \brief Constructor
      \param parent Parent widget
    
    
      Create a compass widget with a scale, no needle and no rose.
    
    pixhawk's avatar
    pixhawk committed
      The default origin is 270.0 with no valid value. It accepts
      mouse and keyboard inputs and has no step size. The default mode
      is QwtDial::RotateNeedle.
    
    Bryant's avatar
    Bryant committed
    QwtCompass::QwtCompass( QWidget* parent ):
        QwtDial( parent )
    
    pixhawk's avatar
    pixhawk committed
    {
    
    Bryant's avatar
    Bryant committed
        d_data = new PrivateData;
    
    pixhawk's avatar
    pixhawk committed
    
    
    Bryant's avatar
    Bryant committed
        setScaleDraw( new QwtCompassScaleDraw() );
    
    pixhawk's avatar
    pixhawk committed
    
    
    Bryant's avatar
    Bryant committed
        setOrigin( 270.0 );
        setWrapping( true );
    
    pixhawk's avatar
    pixhawk committed
    
    
    Bryant's avatar
    Bryant committed
        setScaleMaxMajor( 36 );
        setScaleMaxMinor( 10 );
    
    pixhawk's avatar
    pixhawk committed
    
    
    Bryant's avatar
    Bryant committed
        setScale( 0.0, 360.0 ); // degrees as default
        setTotalSteps( 360 );
    }
    
    pixhawk's avatar
    pixhawk committed
    
    //!  Destructor
    
    QwtCompass::~QwtCompass()
    
    pixhawk's avatar
    pixhawk committed
    {
        delete d_data;
    }
    
    
    
    Bryant's avatar
    Bryant committed
    /*!
       Draw the contents of the scale
    
    pixhawk's avatar
    pixhawk committed
    
    
    Bryant's avatar
    Bryant committed
       \param painter Painter
       \param center Center of the content circle
       \param radius Radius of the content circle
    */
    void QwtCompass::drawScaleContents( QPainter *painter,
        const QPointF &center, double radius ) const
    
    pixhawk's avatar
    pixhawk committed
    {
        QPalette::ColorGroup cg;
        if ( isEnabled() )
            cg = hasFocus() ? QPalette::Active : QPalette::Inactive;
        else
            cg = QPalette::Disabled;
    
        double north = origin();
    
    Bryant's avatar
    Bryant committed
        if ( isValid() )
        {
    
    pixhawk's avatar
    pixhawk committed
            if ( mode() == RotateScale )
    
                north -= value();
    
    pixhawk's avatar
    pixhawk committed
        }
    
        const int margin = 4;
    
    Bryant's avatar
    Bryant committed
        drawRose( painter, center, radius - margin, 360.0 - north,  cg );
    
    pixhawk's avatar
    pixhawk committed
    }
    
    /*!
      Draw the compass rose
    
    pixhawk's avatar
    pixhawk committed
      \param painter Painter
      \param center Center of the compass
      \param radius of the circle, where to paint the rose
      \param north Direction pointing north, in degrees counter clockwise
      \param cg Color group
    */
    
    Bryant's avatar
    Bryant committed
    void QwtCompass::drawRose( QPainter *painter, const QPointF &center,
        double radius, double north, QPalette::ColorGroup cg ) const
    
    pixhawk's avatar
    pixhawk committed
    {
        if ( d_data->rose )
    
    Bryant's avatar
    Bryant committed
            d_data->rose->draw( painter, center, radius, north,  cg );
    
    pixhawk's avatar
    pixhawk committed
    }
    
    /*!
      Set a rose for the compass
      \param rose Compass rose
      \warning The rose will be deleted, when a different rose is
        set or in ~QwtCompass
      \sa rose()
    */
    
    Bryant's avatar
    Bryant committed
    void QwtCompass::setRose( QwtCompassRose *rose )
    
    pixhawk's avatar
    pixhawk committed
    {
    
    Bryant's avatar
    Bryant committed
        if ( rose != d_data->rose )
        {
    
    pixhawk's avatar
    pixhawk committed
            if ( d_data->rose )
                delete d_data->rose;
    
            d_data->rose = rose;
            update();
        }
    }
    
    
    pixhawk's avatar
    pixhawk committed
      \return rose
      \sa setRose()
    */
    
    const QwtCompassRose *QwtCompass::rose() const
    {
        return d_data->rose;
    
    pixhawk's avatar
    pixhawk committed
    }
    
    
    pixhawk's avatar
    pixhawk committed
      \return rose
      \sa setRose()
    */
    
    QwtCompassRose *QwtCompass::rose()
    {
        return d_data->rose;
    
    pixhawk's avatar
    pixhawk committed
    }
    
    
    pixhawk's avatar
    pixhawk committed
      Handles key events
    
      Beside the keys described in QwtDial::keyPressEvent numbers
      from 1-9 (without 5) set the direction according to their
      position on the num pad.
    
      \sa isReadOnly()
    */
    
    Bryant's avatar
    Bryant committed
    void QwtCompass::keyPressEvent( QKeyEvent *kev )
    
    pixhawk's avatar
    pixhawk committed
    {
    
    Bryant's avatar
    Bryant committed
        if ( isReadOnly() )
    
    pixhawk's avatar
    pixhawk committed
            return;
    
    #if 0
    
    Bryant's avatar
    Bryant committed
        if ( kev->key() == Key_5 )
        {
    
    pixhawk's avatar
    pixhawk committed
            invalidate(); // signal ???
            return;
        }
    #endif
    
        double newValue = value();
    
    
    Bryant's avatar
    Bryant committed
        if ( kev->key() >= Qt::Key_1 && kev->key() <= Qt::Key_9 )
        {
    
    pixhawk's avatar
    pixhawk committed
            if ( mode() != RotateNeedle || kev->key() == Qt::Key_5 )
                return;
    
    
    Bryant's avatar
    Bryant committed
            switch ( kev->key() )
            {
                case Qt::Key_6:
                    newValue = 180.0 * 0.0;
                    break;
                case Qt::Key_3:
                    newValue = 180.0 * 0.25;
                    break;
                case Qt::Key_2:
                    newValue = 180.0 * 0.5;
                    break;
                case Qt::Key_1:
                    newValue = 180.0 * 0.75;
                    break;
                case Qt::Key_4:
                    newValue = 180.0 * 1.0;
                    break;
                case Qt::Key_7:
                    newValue = 180.0 * 1.25;
                    break;
                case Qt::Key_8:
                    newValue = 180.0 * 1.5;
                    break;
                case Qt::Key_9:
                    newValue = 180.0 * 1.75;
                    break;
    
    pixhawk's avatar
    pixhawk committed
            }
            newValue -= origin();
    
    Bryant's avatar
    Bryant committed
            setValue( newValue );
        }
        else
        {
            QwtDial::keyPressEvent( kev );
    
    pixhawk's avatar
    pixhawk committed
        }
    }