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
    }
}