qwt_dial_needle.cpp 11 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_dial_needle.h"
#include "qwt_global.h"
pixhawk's avatar
pixhawk committed
12 13
#include "qwt_math.h"
#include "qwt_painter.h"
Bryant's avatar
Bryant committed
14 15
#include <qapplication.h>
#include <qpainter.h>
pixhawk's avatar
pixhawk committed
16

Bryant's avatar
Bryant committed
17 18 19
#if QT_VERSION < 0x040601
#define qFastSin(x) qSin(x)
#define qFastCos(x) qCos(x)
pixhawk's avatar
pixhawk committed
20 21
#endif

Bryant's avatar
Bryant committed
22 23 24
static void qwtDrawStyle1Needle( QPainter *painter,
    const QPalette &palette, QPalette::ColorGroup colorGroup,
    double length )
pixhawk's avatar
pixhawk committed
25
{
Bryant's avatar
Bryant committed
26 27
    const double r[] = { 0.4, 0.3, 1, 0.8, 1, 0.3, 0.4 };
    const double a[] = { -45, -20, -15, 0, 15, 20, 45 };
pixhawk's avatar
pixhawk committed
28

Bryant's avatar
Bryant committed
29 30 31 32 33
    QPainterPath path;
    for ( int i = 0; i < 7; i++ )
    {
        const double angle = a[i] / 180.0 * M_PI;
        const double radius = r[i] * length;
pixhawk's avatar
pixhawk committed
34

Bryant's avatar
Bryant committed
35 36
        const double x = radius * qFastCos( angle );
        const double y = radius * qFastSin( angle );
pixhawk's avatar
pixhawk committed
37

Bryant's avatar
Bryant committed
38 39
        path.lineTo( x, -y );
    }
pixhawk's avatar
pixhawk committed
40

Bryant's avatar
Bryant committed
41 42 43
    painter->setPen( Qt::NoPen );
    painter->setBrush( palette.brush( colorGroup, QPalette::Light ) );
    painter->drawPath( path );
pixhawk's avatar
pixhawk committed
44 45
}

Bryant's avatar
Bryant committed
46 47
static void qwtDrawStyle2Needle( QPainter *painter,
    const QPalette &palette, QPalette::ColorGroup colorGroup, double length )
pixhawk's avatar
pixhawk committed
48
{
Bryant's avatar
Bryant committed
49 50
    const double ratioX = 0.7;
    const double ratioY = 0.3;
pixhawk's avatar
pixhawk committed
51

Bryant's avatar
Bryant committed
52 53 54
    QPainterPath path1;
    path1.lineTo( ratioX * length, 0.0 );
    path1.lineTo( length, ratioY * length );
pixhawk's avatar
pixhawk committed
55

Bryant's avatar
Bryant committed
56 57 58
    QPainterPath path2;
    path2.lineTo( ratioX * length, 0.0 );
    path2.lineTo( length, -ratioY * length );
pixhawk's avatar
pixhawk committed
59

Bryant's avatar
Bryant committed
60
    painter->setPen( Qt::NoPen );
pixhawk's avatar
pixhawk committed
61

Bryant's avatar
Bryant committed
62 63
    painter->setBrush( palette.brush( colorGroup, QPalette::Light ) );
    painter->drawPath( path1 );
pixhawk's avatar
pixhawk committed
64

Bryant's avatar
Bryant committed
65 66 67
    painter->setBrush( palette.brush( colorGroup, QPalette::Dark ) );
    painter->drawPath( path2 );
}
pixhawk's avatar
pixhawk committed
68

Bryant's avatar
Bryant committed
69 70 71 72 73
static void qwtDrawShadedPointer( QPainter *painter, 
    const QColor &lightColor, const QColor &darkColor,
    double length, double width )
{
    const double peak = qMax( length / 10.0, 5.0 );
pixhawk's avatar
pixhawk committed
74

Bryant's avatar
Bryant committed
75 76 77
    const double knobWidth = width + 8;
    QRectF knobRect( 0, 0, knobWidth, knobWidth );
    knobRect.moveCenter( QPointF(0, 0) );
pixhawk's avatar
pixhawk committed
78

Bryant's avatar
Bryant committed
79 80 81 82 83
    QPainterPath path1;
    path1.lineTo( 0.0, 0.5 * width );
    path1.lineTo( length - peak, 0.5 * width );
    path1.lineTo( length, 0.0 );
    path1.lineTo( 0.0, 0.0 );
pixhawk's avatar
pixhawk committed
84

Bryant's avatar
Bryant committed
85 86
    QPainterPath arcPath1;
    arcPath1.arcTo( knobRect, 0.0, -90.0 );
pixhawk's avatar
pixhawk committed
87

Bryant's avatar
Bryant committed
88
    path1 = path1.united( arcPath1 );
pixhawk's avatar
pixhawk committed
89

Bryant's avatar
Bryant committed
90 91 92 93 94
    QPainterPath path2;
    path2.lineTo( 0.0, -0.5 * width );
    path2.lineTo( length - peak, -0.5 * width );
    path2.lineTo( length, 0.0 );
    path2.lineTo( 0.0, 0.0 );
pixhawk's avatar
pixhawk committed
95

Bryant's avatar
Bryant committed
96 97
    QPainterPath arcPath2;
    arcPath2.arcTo( knobRect, 0.0, 90.0 );
pixhawk's avatar
pixhawk committed
98

Bryant's avatar
Bryant committed
99
    path2 = path2.united( arcPath2 );
pixhawk's avatar
pixhawk committed
100

Bryant's avatar
Bryant committed
101
    painter->setPen( Qt::NoPen );
pixhawk's avatar
pixhawk committed
102

Bryant's avatar
Bryant committed
103 104 105 106 107
    painter->setBrush( lightColor );
    painter->drawPath( path1 );

    painter->setBrush( darkColor );
    painter->drawPath( path2 );
pixhawk's avatar
pixhawk committed
108 109
}

Bryant's avatar
Bryant committed
110 111 112
static void qwtDrawArrowNeedle( QPainter *painter,
    const QPalette &palette, QPalette::ColorGroup colorGroup,
    double length, double width )
pixhawk's avatar
pixhawk committed
113 114
{
    if ( width <= 0 )
Bryant's avatar
Bryant committed
115
        width = qMax( length * 0.06, 9.0 );
pixhawk's avatar
pixhawk committed
116

Bryant's avatar
Bryant committed
117
    const double peak = qMax( 2.0, 0.4 * width );
pixhawk's avatar
pixhawk committed
118

Bryant's avatar
Bryant committed
119 120 121 122 123 124
    QPainterPath path;
    path.moveTo( 0.0, 0.5 * width );
    path.lineTo( length - peak, 0.3 * width );
    path.lineTo( length, 0.0 );
    path.lineTo( length - peak, -0.3 * width );
    path.lineTo( 0.0, -0.5 * width );
pixhawk's avatar
pixhawk committed
125

Bryant's avatar
Bryant committed
126
    QRectF br = path.boundingRect();
pixhawk's avatar
pixhawk committed
127

Bryant's avatar
Bryant committed
128 129 130
    QPalette pal( palette.color( QPalette::Mid ) );
    QColor c1 = pal.color( QPalette::Light );
    QColor c2 = pal.color( QPalette::Dark );
pixhawk's avatar
pixhawk committed
131

Bryant's avatar
Bryant committed
132 133 134 135 136
    QLinearGradient gradient( br.topLeft(), br.bottomLeft() );
    gradient.setColorAt( 0.0, c1 );
    gradient.setColorAt( 0.5, c1 );
    gradient.setColorAt( 0.5001, c2 );
    gradient.setColorAt( 1.0, c2 );
pixhawk's avatar
pixhawk committed
137

Bryant's avatar
Bryant committed
138 139
    QPen pen( gradient, 1 );
    pen.setJoinStyle( Qt::MiterJoin );
pixhawk's avatar
pixhawk committed
140

Bryant's avatar
Bryant committed
141 142 143 144 145
    painter->setPen( pen );
    painter->setBrush( palette.brush( colorGroup, QPalette::Mid ) );

    painter->drawPath( path );
}
pixhawk's avatar
pixhawk committed
146

Bryant's avatar
Bryant committed
147 148 149 150 151
static void qwtDrawTriangleNeedle( QPainter *painter,
    const QPalette &palette, QPalette::ColorGroup colorGroup,
    double length )
{
    const double width = qRound( length / 3.0 );
pixhawk's avatar
pixhawk committed
152

Bryant's avatar
Bryant committed
153
    QPainterPath path[4];
pixhawk's avatar
pixhawk committed
154

Bryant's avatar
Bryant committed
155 156
    path[0].lineTo( length, 0.0 );
    path[0].lineTo( 0.0, width / 2 );
pixhawk's avatar
pixhawk committed
157

Bryant's avatar
Bryant committed
158 159
    path[1].lineTo( length, 0.0 );
    path[1].lineTo( 0.0, -width / 2 );
pixhawk's avatar
pixhawk committed
160

Bryant's avatar
Bryant committed
161 162
    path[2].lineTo( -length, 0.0 );
    path[2].lineTo( 0.0, width / 2 );
pixhawk's avatar
pixhawk committed
163

Bryant's avatar
Bryant committed
164 165
    path[3].lineTo( -length, 0.0 );
    path[3].lineTo( 0.0, -width / 2 );
pixhawk's avatar
pixhawk committed
166 167


Bryant's avatar
Bryant committed
168 169 170
    const int colorOffset =  10;
    const QColor darkColor = palette.color( colorGroup, QPalette::Dark );
    const QColor lightColor = palette.color( colorGroup, QPalette::Light );
pixhawk's avatar
pixhawk committed
171

Bryant's avatar
Bryant committed
172 173 174 175 176
    QColor color[4];
    color[0] = darkColor.light( 100 + colorOffset );
    color[1] = darkColor.dark( 100 + colorOffset );
    color[2] = lightColor.light( 100 + colorOffset );
    color[3] = lightColor.dark( 100 + colorOffset );
pixhawk's avatar
pixhawk committed
177

Bryant's avatar
Bryant committed
178
    painter->setPen( Qt::NoPen );
pixhawk's avatar
pixhawk committed
179

Bryant's avatar
Bryant committed
180 181 182 183
    for ( int i = 0; i < 4; i++ )
    {
        painter->setBrush( color[i] );
        painter->drawPath( path[i] );
pixhawk's avatar
pixhawk committed
184 185 186 187
    }
}

//! Constructor
Bryant's avatar
Bryant committed
188 189
QwtDialNeedle::QwtDialNeedle():
    d_palette( QApplication::palette() )
190
{
Bryant's avatar
Bryant committed
191
}
pixhawk's avatar
pixhawk committed
192

Bryant's avatar
Bryant committed
193 194 195
//! Destructor
QwtDialNeedle::~QwtDialNeedle()
{
pixhawk's avatar
pixhawk committed
196 197 198
}

/*!
Bryant's avatar
Bryant committed
199
    Sets the palette for the needle.
pixhawk's avatar
pixhawk committed
200

Bryant's avatar
Bryant committed
201
    \param palette New Palette
pixhawk's avatar
pixhawk committed
202
*/
Bryant's avatar
Bryant committed
203
void QwtDialNeedle::setPalette( const QPalette &palette )
pixhawk's avatar
pixhawk committed
204
{
Bryant's avatar
Bryant committed
205
    d_palette = palette;
pixhawk's avatar
pixhawk committed
206 207 208
}

/*!
Bryant's avatar
Bryant committed
209
  \return the palette of the needle.
pixhawk's avatar
pixhawk committed
210
*/
Bryant's avatar
Bryant committed
211
const QPalette &QwtDialNeedle::palette() const
pixhawk's avatar
pixhawk committed
212
{
Bryant's avatar
Bryant committed
213
    return d_palette;
pixhawk's avatar
pixhawk committed
214 215 216
}

/*!
Bryant's avatar
Bryant committed
217
  Draw the needle
pixhawk's avatar
pixhawk committed
218 219

  \param painter Painter
Bryant's avatar
Bryant committed
220
  \param center Center of the dial, start position for the needle
pixhawk's avatar
pixhawk committed
221
  \param length Length of the needle
Bryant's avatar
Bryant committed
222 223
  \param direction Direction of the needle, in degrees counter clockwise
  \param colorGroup Color group, used for painting
pixhawk's avatar
pixhawk committed
224
*/
Bryant's avatar
Bryant committed
225 226 227
void QwtDialNeedle::draw( QPainter *painter, 
    const QPointF &center, double length, double direction, 
    QPalette::ColorGroup colorGroup ) const
pixhawk's avatar
pixhawk committed
228 229 230
{
    painter->save();

Bryant's avatar
Bryant committed
231 232
    painter->translate( center );
    painter->rotate( -direction );
pixhawk's avatar
pixhawk committed
233

Bryant's avatar
Bryant committed
234
    drawNeedle( painter, length, colorGroup );
pixhawk's avatar
pixhawk committed
235 236 237 238

    painter->restore();
}

Bryant's avatar
Bryant committed
239 240 241
//!  Draw the knob
void QwtDialNeedle::drawKnob( QPainter *painter,
    double width, const QBrush &brush, bool sunken ) const
pixhawk's avatar
pixhawk committed
242
{
Bryant's avatar
Bryant committed
243
    QPalette palette( brush.color() );
pixhawk's avatar
pixhawk committed
244

Bryant's avatar
Bryant committed
245 246
    QColor c1 = palette.color( QPalette::Light );
    QColor c2 = palette.color( QPalette::Dark );
pixhawk's avatar
pixhawk committed
247

Bryant's avatar
Bryant committed
248 249
    if ( sunken )
        qSwap( c1, c2 );
pixhawk's avatar
pixhawk committed
250

Bryant's avatar
Bryant committed
251 252
    QRectF rect( 0.0, 0.0, width, width );
    rect.moveCenter( painter->combinedTransform().map( QPointF() ) );
pixhawk's avatar
pixhawk committed
253

Bryant's avatar
Bryant committed
254 255 256 257 258
    QLinearGradient gradient( rect.topLeft(), rect.bottomRight() );
    gradient.setColorAt( 0.0, c1 );
    gradient.setColorAt( 0.3, c1 );
    gradient.setColorAt( 0.7, c2 );
    gradient.setColorAt( 1.0, c2 );
pixhawk's avatar
pixhawk committed
259

Bryant's avatar
Bryant committed
260
    painter->save();
pixhawk's avatar
pixhawk committed
261

Bryant's avatar
Bryant committed
262
    painter->resetTransform();
pixhawk's avatar
pixhawk committed
263

Bryant's avatar
Bryant committed
264 265 266
    painter->setPen( QPen( gradient, 1 ) );
    painter->setBrush( brush );
    painter->drawEllipse( rect );
pixhawk's avatar
pixhawk committed
267 268 269 270

    painter->restore();
}

271
/*!
Bryant's avatar
Bryant committed
272
  Constructor
pixhawk's avatar
pixhawk committed
273

Bryant's avatar
Bryant committed
274 275 276 277
  \param style Style
  \param hasKnob With/Without knob
  \param mid Middle color
  \param base Base color
pixhawk's avatar
pixhawk committed
278
*/
Bryant's avatar
Bryant committed
279 280 281 282 283
QwtDialSimpleNeedle::QwtDialSimpleNeedle( Style style, bool hasKnob,
        const QColor &mid, const QColor &base ):
    d_style( style ),
    d_hasKnob( hasKnob ),
    d_width( -1 )
pixhawk's avatar
pixhawk committed
284 285
{
    QPalette palette;
Bryant's avatar
Bryant committed
286 287
    palette.setColor( QPalette::Mid, mid );
    palette.setColor( QPalette::Base, base );
pixhawk's avatar
pixhawk committed
288

Bryant's avatar
Bryant committed
289
    setPalette( palette );
pixhawk's avatar
pixhawk committed
290 291 292
}

/*!
Bryant's avatar
Bryant committed
293 294 295 296 297 298 299 300
  Set the width of the needle
  \param width Width
  \sa width()
*/
void QwtDialSimpleNeedle::setWidth( double width )
{
    d_width = width;
}
pixhawk's avatar
pixhawk committed
301

Bryant's avatar
Bryant committed
302 303 304
/*!
  \return the width of the needle
  \sa setWidth()
pixhawk's avatar
pixhawk committed
305
*/
Bryant's avatar
Bryant committed
306
double QwtDialSimpleNeedle::width() const
pixhawk's avatar
pixhawk committed
307
{
Bryant's avatar
Bryant committed
308
    return d_width;
pixhawk's avatar
pixhawk committed
309 310 311
}

/*!
Bryant's avatar
Bryant committed
312
 Draw the needle
pixhawk's avatar
pixhawk committed
313 314 315

 \param painter Painter
 \param length Length of the needle
Bryant's avatar
Bryant committed
316
 \param colorGroup Color group, used for painting
pixhawk's avatar
pixhawk committed
317
*/
Bryant's avatar
Bryant committed
318 319
void QwtDialSimpleNeedle::drawNeedle( QPainter *painter, 
    double length, QPalette::ColorGroup colorGroup ) const
pixhawk's avatar
pixhawk committed
320
{
Bryant's avatar
Bryant committed
321 322
    double knobWidth = 0.0;
    double width = d_width;
pixhawk's avatar
pixhawk committed
323

Bryant's avatar
Bryant committed
324 325 326 327
    if ( d_style == Arrow )
    {
        if ( width <= 0.0 )
            width = qMax(length * 0.06, 6.0);
pixhawk's avatar
pixhawk committed
328

Bryant's avatar
Bryant committed
329 330
        qwtDrawArrowNeedle( painter, 
            palette(), colorGroup, length, width );
pixhawk's avatar
pixhawk committed
331

Bryant's avatar
Bryant committed
332 333 334 335 336 337 338 339 340 341 342 343 344 345
        knobWidth = qMin( width * 2.0, 0.2 * length );
    }
    else
    {
        if ( width <= 0.0 )
            width = 5.0;
        
        QPen pen ( palette().brush( colorGroup, QPalette::Mid ), width );
        pen.setCapStyle( Qt::FlatCap );
    
        painter->setPen( pen );
        painter->drawLine( QPointF( 0.0, 0.0 ), QPointF( length, 0.0 ) );

        knobWidth = qMax( width * 3.0, 5.0 );
pixhawk's avatar
pixhawk committed
346 347
    }

Bryant's avatar
Bryant committed
348 349 350 351 352
    if ( d_hasKnob && knobWidth > 0.0 )
    {
        drawKnob( painter, knobWidth,
            palette().brush( colorGroup, QPalette::Base ), false );
    }
pixhawk's avatar
pixhawk committed
353 354
}

Bryant's avatar
Bryant committed
355 356 357 358
//! Constructor
QwtCompassMagnetNeedle::QwtCompassMagnetNeedle( Style style,
        const QColor &light, const QColor &dark ):
    d_style( style )
pixhawk's avatar
pixhawk committed
359
{
Bryant's avatar
Bryant committed
360 361 362 363
    QPalette palette;
    palette.setColor( QPalette::Light, light );
    palette.setColor( QPalette::Dark, dark );
    palette.setColor( QPalette::Base, Qt::gray );
pixhawk's avatar
pixhawk committed
364

Bryant's avatar
Bryant committed
365 366
    setPalette( palette );
}
pixhawk's avatar
pixhawk committed
367

Bryant's avatar
Bryant committed
368 369
/*!
    Draw the needle
pixhawk's avatar
pixhawk committed
370

Bryant's avatar
Bryant committed
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
    \param painter Painter
    \param length Length of the needle
    \param colorGroup Color group, used for painting
*/
void QwtCompassMagnetNeedle::drawNeedle( QPainter *painter, 
    double length, QPalette::ColorGroup colorGroup ) const
{
    if ( d_style == ThinStyle )
    {
        const double width = qMax( length / 6.0, 3.0 );

        const int colorOffset = 10;

        const QColor light = palette().color( colorGroup, QPalette::Light );
        const QColor dark = palette().color( colorGroup, QPalette::Dark );

        qwtDrawShadedPointer( painter,
            dark.light( 100 + colorOffset ),
            dark.dark( 100 + colorOffset ),
            length, width );
        
        painter->rotate( 180.0 );
    
        qwtDrawShadedPointer( painter,
            light.light( 100 + colorOffset ),
            light.dark( 100 + colorOffset ),
            length, width );
        
        const QBrush baseBrush = palette().brush( colorGroup, QPalette::Base );
        drawKnob( painter, width, baseBrush, true );
    }
    else
    {
        qwtDrawTriangleNeedle( painter, palette(), colorGroup, length );
    }
}
pixhawk's avatar
pixhawk committed
407

Bryant's avatar
Bryant committed
408 409
/*!
   Constructor
pixhawk's avatar
pixhawk committed
410

Bryant's avatar
Bryant committed
411 412 413 414 415 416 417 418 419 420 421
   \param style Arrow style
   \param light Light color
   \param dark Dark color
*/
QwtCompassWindArrow::QwtCompassWindArrow( Style style,
        const QColor &light, const QColor &dark ):
    d_style( style )
{
    QPalette palette;
    palette.setColor( QPalette::Light, light );
    palette.setColor( QPalette::Dark, dark );
pixhawk's avatar
pixhawk committed
422

Bryant's avatar
Bryant committed
423 424
    setPalette( palette );
}
pixhawk's avatar
pixhawk committed
425

Bryant's avatar
Bryant committed
426 427
/*!
 Draw the needle
pixhawk's avatar
pixhawk committed
428

Bryant's avatar
Bryant committed
429 430 431 432 433 434 435 436 437 438 439
 \param painter Painter
 \param length Length of the needle
 \param colorGroup Color group, used for painting
*/
void QwtCompassWindArrow::drawNeedle( QPainter *painter, 
    double length, QPalette::ColorGroup colorGroup ) const
{
    if ( d_style == Style1 )
        qwtDrawStyle1Needle( painter, palette(), colorGroup, length );
    else
        qwtDrawStyle2Needle( painter, palette(), colorGroup, length );
pixhawk's avatar
pixhawk committed
440
}