qwt_scale_widget.cpp 22.1 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
#include "qwt_scale_widget.h"
pixhawk's avatar
pixhawk committed
11 12 13 14 15 16
#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
17 18 19 20 21 22
#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
23 24 25 26 27

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

Bryant's avatar
Bryant committed
33 34
    ~PrivateData()
    {
pixhawk's avatar
pixhawk committed
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
        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
50 51 52 53
    QwtScaleWidget::LayoutFlags layoutFlags;

    struct t_colorBar
    {
pixhawk's avatar
pixhawk committed
54 55
        bool isEnabled;
        int width;
Bryant's avatar
Bryant committed
56
        QwtInterval interval;
pixhawk's avatar
pixhawk committed
57 58 59 60 61 62 63 64
        QwtColorMap *colorMap;
    } colorBar;
};

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

/*!
  \brief Constructor
73
  \param align Alignment.
pixhawk's avatar
pixhawk committed
74 75 76
  \param parent Parent widget
*/
QwtScaleWidget::QwtScaleWidget(
Bryant's avatar
Bryant committed
77 78
        QwtScaleDraw::Alignment align, QWidget *parent ):
    QWidget( parent )
pixhawk's avatar
pixhawk committed
79
{
Bryant's avatar
Bryant committed
80
    initScale( align );
pixhawk's avatar
pixhawk committed
81 82 83 84 85 86 87 88 89
}

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

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

Bryant's avatar
Bryant committed
94 95 96
    d_data->layoutFlags = 0;
    if ( align == QwtScaleDraw::RightScale )
        d_data->layoutFlags |= TitleInverted;
pixhawk's avatar
pixhawk committed
97 98 99 100 101 102 103 104 105 106

    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
107 108 109 110 111
    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
112 113 114 115

    d_data->colorBar.colorMap = new QwtLinearColorMap();
    d_data->colorBar.isEnabled = false;
    d_data->colorBar.width = 10;
116

pixhawk's avatar
pixhawk committed
117
    const int flags = Qt::AlignHCenter
Bryant's avatar
Bryant committed
118 119 120 121 122 123
        | 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
124 125 126
    if ( d_data->scaleDraw->orientation() == Qt::Vertical )
        policy.transpose();

Bryant's avatar
Bryant committed
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
    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;
    }
}
150

Bryant's avatar
Bryant committed
151 152
/*!
   Test a layout flag
pixhawk's avatar
pixhawk committed
153

Bryant's avatar
Bryant committed
154 155 156 157 158 159 160
   \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
161 162
}

Bryant's avatar
Bryant committed
163 164 165 166 167 168 169
/*!
  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
170
{
Bryant's avatar
Bryant committed
171 172 173
    if ( d_data->title.text() != title )
    {
        d_data->title.setText( title );
pixhawk's avatar
pixhawk committed
174 175 176 177 178
        layoutScale();
    }
}

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

pixhawk's avatar
pixhawk committed
181
  \param title New title
Bryant's avatar
Bryant committed
182
  \sa title()
pixhawk's avatar
pixhawk committed
183 184 185 186
  \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
187
void QwtScaleWidget::setTitle( const QwtText &title )
pixhawk's avatar
pixhawk committed
188 189
{
    QwtText t = title;
Bryant's avatar
Bryant committed
190 191
    const int flags = title.renderFlags() & ~( Qt::AlignTop | Qt::AlignBottom );
    t.setRenderFlags( flags );
pixhawk's avatar
pixhawk committed
192

Bryant's avatar
Bryant committed
193 194
    if ( t != d_data->title )
    {
pixhawk's avatar
pixhawk committed
195 196 197 198 199 200 201 202 203
        d_data->title = t;
        layoutScale();
    }
}

/*!
  Change the alignment

  \param alignment New alignment
Bryant's avatar
Bryant committed
204
  \sa alignment()
pixhawk's avatar
pixhawk committed
205
*/
Bryant's avatar
Bryant committed
206
void QwtScaleWidget::setAlignment( QwtScaleDraw::Alignment alignment )
pixhawk's avatar
pixhawk committed
207
{
Bryant's avatar
Bryant committed
208 209 210 211
    if ( d_data->scaleDraw )
        d_data->scaleDraw->setAlignment( alignment );

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

Bryant's avatar
Bryant committed
218 219 220
        setSizePolicy( policy );

        setAttribute( Qt::WA_WState_OwnSizePolicy, false );
pixhawk's avatar
pixhawk committed
221 222 223 224 225
    }

    layoutScale();
}

226 227 228

/*!
    \return position
Bryant's avatar
Bryant committed
229
    \sa setPosition()
pixhawk's avatar
pixhawk committed
230
*/
231
QwtScaleDraw::Alignment QwtScaleWidget::alignment() const
pixhawk's avatar
pixhawk committed
232
{
Bryant's avatar
Bryant committed
233
    if ( !scaleDraw() )
pixhawk's avatar
pixhawk committed
234 235 236 237 238 239 240 241 242 243 244
        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
245
  \sa borderDist()
pixhawk's avatar
pixhawk committed
246
*/
Bryant's avatar
Bryant committed
247
void QwtScaleWidget::setBorderDist( int dist1, int dist2 )
pixhawk's avatar
pixhawk committed
248
{
Bryant's avatar
Bryant committed
249 250
    if ( dist1 != d_data->borderDist[0] || dist2 != d_data->borderDist[1] )
    {
pixhawk's avatar
pixhawk committed
251 252 253 254 255 256 257 258 259
        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
260
  \sa margin()
pixhawk's avatar
pixhawk committed
261
*/
Bryant's avatar
Bryant committed
262
void QwtScaleWidget::setMargin( int margin )
pixhawk's avatar
pixhawk committed
263
{
Bryant's avatar
Bryant committed
264 265 266
    margin = qMax( 0, margin );
    if ( margin != d_data->margin )
    {
pixhawk's avatar
pixhawk committed
267 268 269 270 271 272 273 274
        d_data->margin = margin;
        layoutScale();
    }
}

/*!
  \brief Specify the distance between color bar, scale and title
  \param spacing Spacing
Bryant's avatar
Bryant committed
275
  \sa spacing()
pixhawk's avatar
pixhawk committed
276
*/
Bryant's avatar
Bryant committed
277
void QwtScaleWidget::setSpacing( int spacing )
pixhawk's avatar
pixhawk committed
278
{
Bryant's avatar
Bryant committed
279 280 281
    spacing = qMax( 0, spacing );
    if ( spacing != d_data->spacing )
    {
pixhawk's avatar
pixhawk committed
282 283 284 285 286 287 288 289
        d_data->spacing = spacing;
        layoutScale();
    }
}

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

Bryant's avatar
Bryant committed
290
  \sa QwtScaleDraw::setLabelAlignment(), setLabelRotation()
pixhawk's avatar
pixhawk committed
291
*/
Bryant's avatar
Bryant committed
292
void QwtScaleWidget::setLabelAlignment( Qt::Alignment alignment )
pixhawk's avatar
pixhawk committed
293
{
Bryant's avatar
Bryant committed
294
    d_data->scaleDraw->setLabelAlignment( alignment );
pixhawk's avatar
pixhawk committed
295 296 297 298 299 300
    layoutScale();
}

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

  \param rotation Rotation
  \sa QwtScaleDraw::setLabelRotation(), setLabelFlags()
pixhawk's avatar
pixhawk committed
304
*/
Bryant's avatar
Bryant committed
305
void QwtScaleWidget::setLabelRotation( double rotation )
pixhawk's avatar
pixhawk committed
306
{
Bryant's avatar
Bryant committed
307
    d_data->scaleDraw->setLabelRotation( rotation );
pixhawk's avatar
pixhawk committed
308 309 310 311
    layoutScale();
}

/*!
Bryant's avatar
Bryant committed
312 313 314 315 316 317 318 319 320
  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
321
*/
Bryant's avatar
Bryant committed
322
void QwtScaleWidget::setScaleDraw( QwtScaleDraw *scaleDraw )
pixhawk's avatar
pixhawk committed
323
{
Bryant's avatar
Bryant committed
324
    if ( ( scaleDraw == NULL ) || ( scaleDraw == d_data->scaleDraw ) )
pixhawk's avatar
pixhawk committed
325 326
        return;

Bryant's avatar
Bryant committed
327 328 329 330 331 332 333 334 335 336 337 338
    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
339 340

    delete d_data->scaleDraw;
Bryant's avatar
Bryant committed
341
    d_data->scaleDraw = scaleDraw;
pixhawk's avatar
pixhawk committed
342 343 344 345

    layoutScale();
}

346
/*!
Bryant's avatar
Bryant committed
347 348
    \return scaleDraw of this scale
    \sa setScaleDraw(), QwtScaleDraw::setScaleDraw()
pixhawk's avatar
pixhawk committed
349
*/
350 351 352
const QwtScaleDraw *QwtScaleWidget::scaleDraw() const
{
    return d_data->scaleDraw;
pixhawk's avatar
pixhawk committed
353 354
}

355
/*!
Bryant's avatar
Bryant committed
356 357
    \return scaleDraw of this scale
    \sa QwtScaleDraw::setScaleDraw()
pixhawk's avatar
pixhawk committed
358
*/
359 360 361
QwtScaleDraw *QwtScaleWidget::scaleDraw()
{
    return d_data->scaleDraw;
pixhawk's avatar
pixhawk committed
362 363
}

364 365
/*!
    \return title
Bryant's avatar
Bryant committed
366
    \sa setTitle()
pixhawk's avatar
pixhawk committed
367
*/
368
QwtText QwtScaleWidget::title() const
pixhawk's avatar
pixhawk committed
369 370 371 372
{
    return d_data->title;
}

373 374
/*!
    \return start border distance
Bryant's avatar
Bryant committed
375
    \sa setBorderDist()
pixhawk's avatar
pixhawk committed
376
*/
377 378 379 380
int QwtScaleWidget::startBorderDist() const
{
    return d_data->borderDist[0];
}
pixhawk's avatar
pixhawk committed
381

382 383
/*!
    \return end border distance
Bryant's avatar
Bryant committed
384
    \sa setBorderDist()
pixhawk's avatar
pixhawk committed
385
*/
386 387 388
int QwtScaleWidget::endBorderDist() const
{
    return d_data->borderDist[1];
pixhawk's avatar
pixhawk committed
389 390
}

391
/*!
pixhawk's avatar
pixhawk committed
392
    \return margin
Bryant's avatar
Bryant committed
393
    \sa setMargin()
pixhawk's avatar
pixhawk committed
394
*/
395 396 397
int QwtScaleWidget::margin() const
{
    return d_data->margin;
pixhawk's avatar
pixhawk committed
398 399
}

400
/*!
pixhawk's avatar
pixhawk committed
401
    \return distance between scale and title
Bryant's avatar
Bryant committed
402
    \sa setMargin()
pixhawk's avatar
pixhawk committed
403
*/
404 405 406
int QwtScaleWidget::spacing() const
{
    return d_data->spacing;
pixhawk's avatar
pixhawk committed
407 408
}

409
/*!
Bryant's avatar
Bryant committed
410
  \brief paintEvent
pixhawk's avatar
pixhawk committed
411
*/
Bryant's avatar
Bryant committed
412
void QwtScaleWidget::paintEvent( QPaintEvent *event )
pixhawk's avatar
pixhawk committed
413
{
Bryant's avatar
Bryant committed
414 415 416 417 418 419 420 421
    QPainter painter( this );
    painter.setClipRegion( event->region() );

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

    draw( &painter );
422
}
Bryant's avatar
Bryant committed
423

pixhawk's avatar
pixhawk committed
424
/*!
Bryant's avatar
Bryant committed
425
  \brief draw the scale
pixhawk's avatar
pixhawk committed
426
*/
Bryant's avatar
Bryant committed
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
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
442
    }
Bryant's avatar
Bryant committed
443 444 445 446 447 448 449 450
    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
451 452 453
}

/*!
Bryant's avatar
Bryant committed
454 455 456 457
  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
458
*/
Bryant's avatar
Bryant committed
459
QRectF QwtScaleWidget::colorBarRect( const QRectF& rect ) const
pixhawk's avatar
pixhawk committed
460
{
Bryant's avatar
Bryant committed
461
    QRectF cr = rect;
pixhawk's avatar
pixhawk committed
462

Bryant's avatar
Bryant committed
463 464 465 466
    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
467
    }
Bryant's avatar
Bryant committed
468 469 470 471
    else
    {
        cr.setTop( cr.top() + d_data->borderDist[0] );
        cr.setHeight( cr.height() - d_data->borderDist[1] + 1 );
pixhawk's avatar
pixhawk committed
472 473
    }

Bryant's avatar
Bryant committed
474 475
    switch ( d_data->scaleDraw->alignment() )
    {
476
        case QwtScaleDraw::LeftScale:
Bryant's avatar
Bryant committed
477 478 479 480
        {
            cr.setLeft( cr.right() - d_data->margin
                - d_data->colorBar.width );
            cr.setWidth( d_data->colorBar.width );
481
            break;
Bryant's avatar
Bryant committed
482
        }
483 484

        case QwtScaleDraw::RightScale:
Bryant's avatar
Bryant committed
485 486 487
        {
            cr.setLeft( cr.left() + d_data->margin );
            cr.setWidth( d_data->colorBar.width );
488
            break;
Bryant's avatar
Bryant committed
489
        }
490 491

        case QwtScaleDraw::BottomScale:
Bryant's avatar
Bryant committed
492 493 494
        {
            cr.setTop( cr.top() + d_data->margin );
            cr.setHeight( d_data->colorBar.width );
495
            break;
Bryant's avatar
Bryant committed
496
        }
497 498

        case QwtScaleDraw::TopScale:
Bryant's avatar
Bryant committed
499 500 501 502
        {
            cr.setTop( cr.bottom() - d_data->margin
                - d_data->colorBar.width );
            cr.setHeight( d_data->colorBar.width );
503
            break;
pixhawk's avatar
pixhawk committed
504 505 506 507 508 509 510
        }
    }

    return cr;
}

/*!
Bryant's avatar
Bryant committed
511 512
  Event handler for resize events
  \param event Resize event
pixhawk's avatar
pixhawk committed
513
*/
Bryant's avatar
Bryant committed
514
void QwtScaleWidget::resizeEvent( QResizeEvent *event )
pixhawk's avatar
pixhawk committed
515
{
Bryant's avatar
Bryant committed
516 517
    Q_UNUSED( event );
    layoutScale( false );
pixhawk's avatar
pixhawk committed
518 519
}

Bryant's avatar
Bryant committed
520 521 522 523 524 525 526
/*!
  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
527 528 529 530

void QwtScaleWidget::layoutScale( bool update_geometry )
{
    int bd0, bd1;
Bryant's avatar
Bryant committed
531
    getBorderDistHint( bd0, bd1 );
pixhawk's avatar
pixhawk committed
532 533 534 535 536 537 538 539 540
    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
541 542
    const QRectF r = contentsRect();
    double x, y, length;
pixhawk's avatar
pixhawk committed
543

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

        if ( d_data->scaleDraw->alignment() == QwtScaleDraw::LeftScale )
Bryant's avatar
Bryant committed
550
            x = r.right() - 1.0 - d_data->margin - colorBarWidth;
pixhawk's avatar
pixhawk committed
551 552
        else
            x = r.left() + d_data->margin + colorBarWidth;
Bryant's avatar
Bryant committed
553 554 555
    }
    else
    {
556
        x = r.left() + bd0;
Bryant's avatar
Bryant committed
557
        length = r.width() - ( bd0 + bd1 );
pixhawk's avatar
pixhawk committed
558 559 560 561

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

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

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

Bryant's avatar
Bryant committed
570 571 572 573 574
    d_data->titleOffset =
        d_data->margin + d_data->spacing + colorBarWidth + extent;

    if ( update_geometry )
    {
575 576
        updateGeometry();
        update();
pixhawk's avatar
pixhawk committed
577 578 579
    }
}

Bryant's avatar
Bryant committed
580 581 582 583 584 585 586 587 588
/*!
  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
589 590 591 592 593 594
{
    if ( !d_data->colorBar.interval.isValid() )
        return;

    const QwtScaleDraw* sd = d_data->scaleDraw;

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

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

pixhawk's avatar
pixhawk committed
603 604 605 606 607
  \param painter Painter
  \param align Alignment
  \param rect Bounding rectangle
*/

Bryant's avatar
Bryant committed
608 609
void QwtScaleWidget::drawTitle( QPainter *painter,
    QwtScaleDraw::Alignment align, const QRectF &rect ) const
pixhawk's avatar
pixhawk committed
610
{
Bryant's avatar
Bryant committed
611
    QRectF r = rect;
pixhawk's avatar
pixhawk committed
612
    double angle;
613
    int flags = d_data->title.renderFlags() &
Bryant's avatar
Bryant committed
614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654
        ~( 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
655 656 657
    }

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

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

    QwtText title = d_data->title;
Bryant's avatar
Bryant committed
666 667
    title.setRenderFlags( flags );
    title.draw( painter, QRectF( 0.0, 0.0, r.width(), r.height() ) );
pixhawk's avatar
pixhawk committed
668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703

    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
704 705 706 707 708 709 710 711
    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
712 713
        // compensate for long titles
        length = dim;
Bryant's avatar
Bryant committed
714
        dim = dimForLength( length, font() );
pixhawk's avatar
pixhawk committed
715 716
    }

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

Bryant's avatar
Bryant committed
721 722 723
    int left, right, top, bottom;
    getContentsMargins( &left, &top, &right, &bottom );
    return size + QSize( left + right, top + bottom );
pixhawk's avatar
pixhawk committed
724 725 726 727 728 729 730 731
}

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

Bryant's avatar
Bryant committed
732
int QwtScaleWidget::titleHeightForWidth( int width ) const
pixhawk's avatar
pixhawk committed
733
{
Bryant's avatar
Bryant committed
734
    return qCeil( d_data->title.heightForWidth( width, font() ) );
pixhawk's avatar
pixhawk committed
735 736 737 738 739 740 741 742 743 744 745
}

/*!
  \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
746
int QwtScaleWidget::dimForLength( int length, const QFont &scaleFont ) const
pixhawk's avatar
pixhawk committed
747
{
Bryant's avatar
Bryant committed
748 749 750
    const int extent = qCeil( d_data->scaleDraw->extent( scaleFont ) );

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

    if ( !d_data->title.isEmpty() )
Bryant's avatar
Bryant committed
753
        dim += titleHeightForWidth( length ) + d_data->spacing;
pixhawk's avatar
pixhawk committed
754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769

    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
770 771 772 773 774
  \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
775 776 777 778
  \warning
  <ul> <li>The minimum border distance depends on the font.</ul>
  \sa setMinBorderDist(), getMinBorderDist(), setBorderDist()
*/
Bryant's avatar
Bryant committed
779
void QwtScaleWidget::getBorderDistHint( int &start, int &end ) const
pixhawk's avatar
pixhawk committed
780
{
Bryant's avatar
Bryant committed
781
    d_data->scaleDraw->getBorderDistHint( font(), start, end );
pixhawk's avatar
pixhawk committed
782 783 784 785 786 787 788 789 790

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

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

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

Bryant's avatar
Bryant committed
796 797
  \param start Minimum for the start border
  \param end Minimum for the end border
pixhawk's avatar
pixhawk committed
798 799
  \sa getMinBorderDist(), getBorderDistHint()
*/
Bryant's avatar
Bryant committed
800
void QwtScaleWidget::setMinBorderDist( int start, int end )
pixhawk's avatar
pixhawk committed
801 802 803 804 805 806
{
    d_data->minBorderDist[0] = start;
    d_data->minBorderDist[1] = end;
}

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

Bryant's avatar
Bryant committed
810 811 812 813 814
  \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
815 816
  \sa setMinBorderDist(), getBorderDistHint()
*/
Bryant's avatar
Bryant committed
817
void QwtScaleWidget::getMinBorderDist( int &start, int &end ) const
pixhawk's avatar
pixhawk committed
818 819 820 821 822 823 824 825 826 827 828 829 830
{
    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
831
void QwtScaleWidget::setScaleDiv( const QwtScaleDiv &scaleDiv )
pixhawk's avatar
pixhawk committed
832 833
{
    QwtScaleDraw *sd = d_data->scaleDraw;
Bryant's avatar
Bryant committed
834 835 836
    if ( sd->scaleDiv() != scaleDiv )
    {
        sd->setScaleDiv( scaleDiv );
pixhawk's avatar
pixhawk committed
837 838
        layoutScale();

Bryant's avatar
Bryant committed
839 840
        Q_EMIT scaleDivChanged();
    }
pixhawk's avatar
pixhawk committed
841 842
}

Bryant's avatar
Bryant committed
843 844 845 846 847 848 849
/*!
  Set the transformation

  \param transformation Transformation
  \sa QwtAbstractScaleDraw::scaleDraw(), QwtScaleMap
 */
void QwtScaleWidget::setTransformation( QwtTransform *transformation )
pixhawk's avatar
pixhawk committed
850
{
Bryant's avatar
Bryant committed
851 852 853 854 855 856 857 858 859 860 861 862
    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
863 864 865 866 867
        d_data->colorBar.isEnabled = on;
        layoutScale();
    }
}

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

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

Bryant's avatar
Bryant committed
880 881 882 883
  \param width Width
  \sa colorBarWidth(), setColorBarEnabled()
*/
void QwtScaleWidget::setColorBarWidth( int width )
pixhawk's avatar
pixhawk committed
884
{
Bryant's avatar
Bryant committed
885 886
    if ( width != d_data->colorBar.width )
    {
pixhawk's avatar
pixhawk committed
887 888 889 890 891 892
        d_data->colorBar.width = width;
        if ( isColorBarEnabled() )
            layoutScale();
    }
}

Bryant's avatar
Bryant committed
893 894 895 896
/*!
  \return Width of the color bar
  \sa setColorBarEnabled(), setColorBarEnabled()
*/
pixhawk's avatar
pixhawk committed
897 898 899 900 901
int QwtScaleWidget::colorBarWidth() const
{
    return d_data->colorBar.width;
}

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

Bryant's avatar
Bryant committed
911 912 913 914 915 916 917 918 919 920 921
/*!
  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
922 923 924
{
    d_data->colorBar.interval = interval;

Bryant's avatar
Bryant committed
925 926 927 928 929
    if ( colorMap != d_data->colorBar.colorMap )
    {
        delete d_data->colorBar.colorMap;
        d_data->colorBar.colorMap = colorMap;
    }
pixhawk's avatar
pixhawk committed
930 931 932 933 934

    if ( isColorBarEnabled() )
        layoutScale();
}

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