qwt_compass.cpp 7.23 KB
Newer Older
pixhawk's avatar
pixhawk committed
1 2 3 4 5 6 7 8 9
/* -*- 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
10 11
#include "qwt_compass.h"
#include "qwt_compass_rose.h"
pixhawk's avatar
pixhawk committed
12 13 14 15
#include "qwt_math.h"
#include "qwt_scale_draw.h"
#include "qwt_painter.h"
#include "qwt_dial_needle.h"
Bryant's avatar
Bryant committed
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
#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
115 116 117 118 119

class QwtCompass::PrivateData
{
public:
    PrivateData():
Bryant's avatar
Bryant committed
120 121
        rose( NULL )
    {
pixhawk's avatar
pixhawk committed
122 123
    }

Bryant's avatar
Bryant committed
124 125
    ~PrivateData()
    {
pixhawk's avatar
pixhawk committed
126 127 128 129 130 131 132 133 134 135
        delete rose;
    }

    QwtCompassRose *rose;
};

/*!
  \brief Constructor
  \param parent Parent widget

136
  Create a compass widget with a scale, no needle and no rose.
pixhawk's avatar
pixhawk committed
137 138 139
  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.
140
*/
Bryant's avatar
Bryant committed
141 142
QwtCompass::QwtCompass( QWidget* parent ):
    QwtDial( parent )
pixhawk's avatar
pixhawk committed
143
{
Bryant's avatar
Bryant committed
144
    d_data = new PrivateData;
pixhawk's avatar
pixhawk committed
145

Bryant's avatar
Bryant committed
146
    setScaleDraw( new QwtCompassScaleDraw() );
pixhawk's avatar
pixhawk committed
147

Bryant's avatar
Bryant committed
148 149
    setOrigin( 270.0 );
    setWrapping( true );
pixhawk's avatar
pixhawk committed
150

Bryant's avatar
Bryant committed
151 152
    setScaleMaxMajor( 36 );
    setScaleMaxMinor( 10 );
pixhawk's avatar
pixhawk committed
153

Bryant's avatar
Bryant committed
154 155 156
    setScale( 0.0, 360.0 ); // degrees as default
    setTotalSteps( 360 );
}
pixhawk's avatar
pixhawk committed
157 158

//!  Destructor
159
QwtCompass::~QwtCompass()
pixhawk's avatar
pixhawk committed
160 161 162 163 164
{
    delete d_data;
}


Bryant's avatar
Bryant committed
165 166
/*!
   Draw the contents of the scale
pixhawk's avatar
pixhawk committed
167

Bryant's avatar
Bryant committed
168 169 170 171 172 173
   \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
174 175 176 177 178 179 180 181
{
    QPalette::ColorGroup cg;
    if ( isEnabled() )
        cg = hasFocus() ? QPalette::Active : QPalette::Inactive;
    else
        cg = QPalette::Disabled;

    double north = origin();
Bryant's avatar
Bryant committed
182 183
    if ( isValid() )
    {
pixhawk's avatar
pixhawk committed
184
        if ( mode() == RotateScale )
185
            north -= value();
pixhawk's avatar
pixhawk committed
186 187 188
    }

    const int margin = 4;
Bryant's avatar
Bryant committed
189
    drawRose( painter, center, radius - margin, 360.0 - north,  cg );
pixhawk's avatar
pixhawk committed
190 191 192 193
}

/*!
  Draw the compass rose
194

pixhawk's avatar
pixhawk committed
195 196 197 198 199 200
  \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
201 202
void QwtCompass::drawRose( QPainter *painter, const QPointF &center,
    double radius, double north, QPalette::ColorGroup cg ) const
pixhawk's avatar
pixhawk committed
203 204
{
    if ( d_data->rose )
Bryant's avatar
Bryant committed
205
        d_data->rose->draw( painter, center, radius, north,  cg );
pixhawk's avatar
pixhawk committed
206 207 208 209 210 211 212 213 214
}

/*!
  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
215
void QwtCompass::setRose( QwtCompassRose *rose )
pixhawk's avatar
pixhawk committed
216
{
Bryant's avatar
Bryant committed
217 218
    if ( rose != d_data->rose )
    {
pixhawk's avatar
pixhawk committed
219 220 221 222 223 224 225 226
        if ( d_data->rose )
            delete d_data->rose;

        d_data->rose = rose;
        update();
    }
}

227
/*!
pixhawk's avatar
pixhawk committed
228 229 230
  \return rose
  \sa setRose()
*/
231 232 233
const QwtCompassRose *QwtCompass::rose() const
{
    return d_data->rose;
pixhawk's avatar
pixhawk committed
234 235
}

236
/*!
pixhawk's avatar
pixhawk committed
237 238 239
  \return rose
  \sa setRose()
*/
240 241 242
QwtCompassRose *QwtCompass::rose()
{
    return d_data->rose;
pixhawk's avatar
pixhawk committed
243 244
}

245
/*!
pixhawk's avatar
pixhawk committed
246 247 248 249 250 251 252 253
  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
254
void QwtCompass::keyPressEvent( QKeyEvent *kev )
pixhawk's avatar
pixhawk committed
255
{
Bryant's avatar
Bryant committed
256
    if ( isReadOnly() )
pixhawk's avatar
pixhawk committed
257 258 259
        return;

#if 0
Bryant's avatar
Bryant committed
260 261
    if ( kev->key() == Key_5 )
    {
pixhawk's avatar
pixhawk committed
262 263 264 265 266 267 268
        invalidate(); // signal ???
        return;
    }
#endif

    double newValue = value();

Bryant's avatar
Bryant committed
269 270
    if ( kev->key() >= Qt::Key_1 && kev->key() <= Qt::Key_9 )
    {
pixhawk's avatar
pixhawk committed
271 272 273
        if ( mode() != RotateNeedle || kev->key() == Qt::Key_5 )
            return;

Bryant's avatar
Bryant committed
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
        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
300 301
        }
        newValue -= origin();
Bryant's avatar
Bryant committed
302 303 304 305 306
        setValue( newValue );
    }
    else
    {
        QwtDial::keyPressEvent( kev );
pixhawk's avatar
pixhawk committed
307 308
    }
}