00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "qwt_scale_widget.h"
00011 #include "qwt_painter.h"
00012 #include "qwt_color_map.h"
00013 #include "qwt_scale_map.h"
00014 #include "qwt_math.h"
00015 #include "qwt_scale_div.h"
00016 #include "qwt_text.h"
00017 #include "qwt_scale_engine.h"
00018 #include <qpainter.h>
00019 #include <qevent.h>
00020 #include <qmath.h>
00021 #include <qstyle.h>
00022 #include <qstyleoption.h>
00023
00024 class QwtScaleWidget::PrivateData
00025 {
00026 public:
00027 PrivateData():
00028 scaleDraw( NULL )
00029 {
00030 colorBar.colorMap = NULL;
00031 }
00032
00033 ~PrivateData()
00034 {
00035 delete scaleDraw;
00036 delete colorBar.colorMap;
00037 }
00038
00039 QwtScaleDraw *scaleDraw;
00040
00041 int borderDist[2];
00042 int minBorderDist[2];
00043 int scaleLength;
00044 int margin;
00045
00046 int titleOffset;
00047 int spacing;
00048 QwtText title;
00049
00050 QwtScaleWidget::LayoutFlags layoutFlags;
00051
00052 struct t_colorBar
00053 {
00054 bool isEnabled;
00055 int width;
00056 QwtInterval interval;
00057 QwtColorMap *colorMap;
00058 } colorBar;
00059 };
00060
00065 QwtScaleWidget::QwtScaleWidget( QWidget *parent ):
00066 QWidget( parent )
00067 {
00068 initScale( QwtScaleDraw::LeftScale );
00069 }
00070
00076 QwtScaleWidget::QwtScaleWidget(
00077 QwtScaleDraw::Alignment align, QWidget *parent ):
00078 QWidget( parent )
00079 {
00080 initScale( align );
00081 }
00082
00084 QwtScaleWidget::~QwtScaleWidget()
00085 {
00086 delete d_data;
00087 }
00088
00090 void QwtScaleWidget::initScale( QwtScaleDraw::Alignment align )
00091 {
00092 d_data = new PrivateData;
00093
00094 d_data->layoutFlags = 0;
00095 if ( align == QwtScaleDraw::RightScale )
00096 d_data->layoutFlags |= TitleInverted;
00097
00098 d_data->borderDist[0] = 0;
00099 d_data->borderDist[1] = 0;
00100 d_data->minBorderDist[0] = 0;
00101 d_data->minBorderDist[1] = 0;
00102 d_data->margin = 4;
00103 d_data->titleOffset = 0;
00104 d_data->spacing = 2;
00105
00106 d_data->scaleDraw = new QwtScaleDraw;
00107 d_data->scaleDraw->setAlignment( align );
00108 d_data->scaleDraw->setLength( 10 );
00109
00110 d_data->scaleDraw->setScaleDiv(
00111 QwtLinearScaleEngine().divideScale( 0.0, 100.0, 10, 5 ) );
00112
00113 d_data->colorBar.colorMap = new QwtLinearColorMap();
00114 d_data->colorBar.isEnabled = false;
00115 d_data->colorBar.width = 10;
00116
00117 const int flags = Qt::AlignHCenter
00118 | Qt::TextExpandTabs | Qt::TextWordWrap;
00119 d_data->title.setRenderFlags( flags );
00120 d_data->title.setFont( font() );
00121
00122 QSizePolicy policy( QSizePolicy::MinimumExpanding,
00123 QSizePolicy::Fixed );
00124 if ( d_data->scaleDraw->orientation() == Qt::Vertical )
00125 policy.transpose();
00126
00127 setSizePolicy( policy );
00128
00129 setAttribute( Qt::WA_WState_OwnSizePolicy, false );
00130 }
00131
00140 void QwtScaleWidget::setLayoutFlag( LayoutFlag flag, bool on )
00141 {
00142 if ( ( ( d_data->layoutFlags & flag ) != 0 ) != on )
00143 {
00144 if ( on )
00145 d_data->layoutFlags |= flag;
00146 else
00147 d_data->layoutFlags &= ~flag;
00148 }
00149 }
00150
00158 bool QwtScaleWidget::testLayoutFlag( LayoutFlag flag ) const
00159 {
00160 return ( d_data->layoutFlags & flag );
00161 }
00162
00169 void QwtScaleWidget::setTitle( const QString &title )
00170 {
00171 if ( d_data->title.text() != title )
00172 {
00173 d_data->title.setText( title );
00174 layoutScale();
00175 }
00176 }
00177
00187 void QwtScaleWidget::setTitle( const QwtText &title )
00188 {
00189 QwtText t = title;
00190 const int flags = title.renderFlags() & ~( Qt::AlignTop | Qt::AlignBottom );
00191 t.setRenderFlags( flags );
00192
00193 if ( t != d_data->title )
00194 {
00195 d_data->title = t;
00196 layoutScale();
00197 }
00198 }
00199
00206 void QwtScaleWidget::setAlignment( QwtScaleDraw::Alignment alignment )
00207 {
00208 if ( d_data->scaleDraw )
00209 d_data->scaleDraw->setAlignment( alignment );
00210
00211 if ( !testAttribute( Qt::WA_WState_OwnSizePolicy ) )
00212 {
00213 QSizePolicy policy( QSizePolicy::MinimumExpanding,
00214 QSizePolicy::Fixed );
00215 if ( d_data->scaleDraw->orientation() == Qt::Vertical )
00216 policy.transpose();
00217
00218 setSizePolicy( policy );
00219
00220 setAttribute( Qt::WA_WState_OwnSizePolicy, false );
00221 }
00222
00223 layoutScale();
00224 }
00225
00226
00231 QwtScaleDraw::Alignment QwtScaleWidget::alignment() const
00232 {
00233 if ( !scaleDraw() )
00234 return QwtScaleDraw::LeftScale;
00235
00236 return scaleDraw()->alignment();
00237 }
00238
00247 void QwtScaleWidget::setBorderDist( int dist1, int dist2 )
00248 {
00249 if ( dist1 != d_data->borderDist[0] || dist2 != d_data->borderDist[1] )
00250 {
00251 d_data->borderDist[0] = dist1;
00252 d_data->borderDist[1] = dist2;
00253 layoutScale();
00254 }
00255 }
00256
00262 void QwtScaleWidget::setMargin( int margin )
00263 {
00264 margin = qMax( 0, margin );
00265 if ( margin != d_data->margin )
00266 {
00267 d_data->margin = margin;
00268 layoutScale();
00269 }
00270 }
00271
00277 void QwtScaleWidget::setSpacing( int spacing )
00278 {
00279 spacing = qMax( 0, spacing );
00280 if ( spacing != d_data->spacing )
00281 {
00282 d_data->spacing = spacing;
00283 layoutScale();
00284 }
00285 }
00286
00292 void QwtScaleWidget::setLabelAlignment( Qt::Alignment alignment )
00293 {
00294 d_data->scaleDraw->setLabelAlignment( alignment );
00295 layoutScale();
00296 }
00297
00305 void QwtScaleWidget::setLabelRotation( double rotation )
00306 {
00307 d_data->scaleDraw->setLabelRotation( rotation );
00308 layoutScale();
00309 }
00310
00322 void QwtScaleWidget::setScaleDraw( QwtScaleDraw *scaleDraw )
00323 {
00324 if ( ( scaleDraw == NULL ) || ( scaleDraw == d_data->scaleDraw ) )
00325 return;
00326
00327 const QwtScaleDraw* sd = d_data->scaleDraw;
00328 if ( sd )
00329 {
00330 scaleDraw->setAlignment( sd->alignment() );
00331 scaleDraw->setScaleDiv( sd->scaleDiv() );
00332
00333 QwtTransform *transform = NULL;
00334 if ( sd->scaleMap().transformation() )
00335 transform = sd->scaleMap().transformation()->copy();
00336
00337 scaleDraw->setTransformation( transform );
00338 }
00339
00340 delete d_data->scaleDraw;
00341 d_data->scaleDraw = scaleDraw;
00342
00343 layoutScale();
00344 }
00345
00350 const QwtScaleDraw *QwtScaleWidget::scaleDraw() const
00351 {
00352 return d_data->scaleDraw;
00353 }
00354
00359 QwtScaleDraw *QwtScaleWidget::scaleDraw()
00360 {
00361 return d_data->scaleDraw;
00362 }
00363
00368 QwtText QwtScaleWidget::title() const
00369 {
00370 return d_data->title;
00371 }
00372
00377 int QwtScaleWidget::startBorderDist() const
00378 {
00379 return d_data->borderDist[0];
00380 }
00381
00386 int QwtScaleWidget::endBorderDist() const
00387 {
00388 return d_data->borderDist[1];
00389 }
00390
00395 int QwtScaleWidget::margin() const
00396 {
00397 return d_data->margin;
00398 }
00399
00404 int QwtScaleWidget::spacing() const
00405 {
00406 return d_data->spacing;
00407 }
00408
00412 void QwtScaleWidget::paintEvent( QPaintEvent *event )
00413 {
00414 QPainter painter( this );
00415 painter.setClipRegion( event->region() );
00416
00417 QStyleOption opt;
00418 opt.init(this);
00419 style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
00420
00421 draw( &painter );
00422 }
00423
00427 void QwtScaleWidget::draw( QPainter *painter ) const
00428 {
00429 d_data->scaleDraw->draw( painter, palette() );
00430
00431 if ( d_data->colorBar.isEnabled && d_data->colorBar.width > 0 &&
00432 d_data->colorBar.interval.isValid() )
00433 {
00434 drawColorBar( painter, colorBarRect( contentsRect() ) );
00435 }
00436
00437 QRect r = contentsRect();
00438 if ( d_data->scaleDraw->orientation() == Qt::Horizontal )
00439 {
00440 r.setLeft( r.left() + d_data->borderDist[0] );
00441 r.setWidth( r.width() - d_data->borderDist[1] );
00442 }
00443 else
00444 {
00445 r.setTop( r.top() + d_data->borderDist[0] );
00446 r.setHeight( r.height() - d_data->borderDist[1] );
00447 }
00448
00449 if ( !d_data->title.isEmpty() )
00450 drawTitle( painter, d_data->scaleDraw->alignment(), r );
00451 }
00452
00459 QRectF QwtScaleWidget::colorBarRect( const QRectF& rect ) const
00460 {
00461 QRectF cr = rect;
00462
00463 if ( d_data->scaleDraw->orientation() == Qt::Horizontal )
00464 {
00465 cr.setLeft( cr.left() + d_data->borderDist[0] );
00466 cr.setWidth( cr.width() - d_data->borderDist[1] + 1 );
00467 }
00468 else
00469 {
00470 cr.setTop( cr.top() + d_data->borderDist[0] );
00471 cr.setHeight( cr.height() - d_data->borderDist[1] + 1 );
00472 }
00473
00474 switch ( d_data->scaleDraw->alignment() )
00475 {
00476 case QwtScaleDraw::LeftScale:
00477 {
00478 cr.setLeft( cr.right() - d_data->margin
00479 - d_data->colorBar.width );
00480 cr.setWidth( d_data->colorBar.width );
00481 break;
00482 }
00483
00484 case QwtScaleDraw::RightScale:
00485 {
00486 cr.setLeft( cr.left() + d_data->margin );
00487 cr.setWidth( d_data->colorBar.width );
00488 break;
00489 }
00490
00491 case QwtScaleDraw::BottomScale:
00492 {
00493 cr.setTop( cr.top() + d_data->margin );
00494 cr.setHeight( d_data->colorBar.width );
00495 break;
00496 }
00497
00498 case QwtScaleDraw::TopScale:
00499 {
00500 cr.setTop( cr.bottom() - d_data->margin
00501 - d_data->colorBar.width );
00502 cr.setHeight( d_data->colorBar.width );
00503 break;
00504 }
00505 }
00506
00507 return cr;
00508 }
00509
00516 void QwtScaleWidget::changeEvent( QEvent *event )
00517 {
00518 if ( event->type() == QEvent::LocaleChange )
00519 {
00520 d_data->scaleDraw->invalidateCache();
00521 }
00522
00523 QWidget::changeEvent( event );
00524 }
00525
00530 void QwtScaleWidget::resizeEvent( QResizeEvent *event )
00531 {
00532 Q_UNUSED( event );
00533 layoutScale( false );
00534 }
00535
00544 void QwtScaleWidget::layoutScale( bool update_geometry )
00545 {
00546 int bd0, bd1;
00547 getBorderDistHint( bd0, bd1 );
00548 if ( d_data->borderDist[0] > bd0 )
00549 bd0 = d_data->borderDist[0];
00550 if ( d_data->borderDist[1] > bd1 )
00551 bd1 = d_data->borderDist[1];
00552
00553 int colorBarWidth = 0;
00554 if ( d_data->colorBar.isEnabled && d_data->colorBar.interval.isValid() )
00555 colorBarWidth = d_data->colorBar.width + d_data->spacing;
00556
00557 const QRectF r = contentsRect();
00558 double x, y, length;
00559
00560 if ( d_data->scaleDraw->orientation() == Qt::Vertical )
00561 {
00562 y = r.top() + bd0;
00563 length = r.height() - ( bd0 + bd1 );
00564
00565 if ( d_data->scaleDraw->alignment() == QwtScaleDraw::LeftScale )
00566 x = r.right() - 1.0 - d_data->margin - colorBarWidth;
00567 else
00568 x = r.left() + d_data->margin + colorBarWidth;
00569 }
00570 else
00571 {
00572 x = r.left() + bd0;
00573 length = r.width() - ( bd0 + bd1 );
00574
00575 if ( d_data->scaleDraw->alignment() == QwtScaleDraw::BottomScale )
00576 y = r.top() + d_data->margin + colorBarWidth;
00577 else
00578 y = r.bottom() - 1.0 - d_data->margin - colorBarWidth;
00579 }
00580
00581 d_data->scaleDraw->move( x, y );
00582 d_data->scaleDraw->setLength( length );
00583
00584 const int extent = qCeil( d_data->scaleDraw->extent( font() ) );
00585
00586 d_data->titleOffset =
00587 d_data->margin + d_data->spacing + colorBarWidth + extent;
00588
00589 if ( update_geometry )
00590 {
00591 updateGeometry();
00592 update();
00593 }
00594 }
00595
00604 void QwtScaleWidget::drawColorBar( QPainter *painter, const QRectF& rect ) const
00605 {
00606 if ( !d_data->colorBar.interval.isValid() )
00607 return;
00608
00609 const QwtScaleDraw* sd = d_data->scaleDraw;
00610
00611 QwtPainter::drawColorBar( painter, *d_data->colorBar.colorMap,
00612 d_data->colorBar.interval.normalized(), sd->scaleMap(),
00613 sd->orientation(), rect );
00614 }
00615
00624 void QwtScaleWidget::drawTitle( QPainter *painter,
00625 QwtScaleDraw::Alignment align, const QRectF &rect ) const
00626 {
00627 QRectF r = rect;
00628 double angle;
00629 int flags = d_data->title.renderFlags() &
00630 ~( Qt::AlignTop | Qt::AlignBottom | Qt::AlignVCenter );
00631
00632 switch ( align )
00633 {
00634 case QwtScaleDraw::LeftScale:
00635 angle = -90.0;
00636 flags |= Qt::AlignTop;
00637 r.setRect( r.left(), r.bottom(),
00638 r.height(), r.width() - d_data->titleOffset );
00639 break;
00640
00641 case QwtScaleDraw::RightScale:
00642 angle = -90.0;
00643 flags |= Qt::AlignTop;
00644 r.setRect( r.left() + d_data->titleOffset, r.bottom(),
00645 r.height(), r.width() - d_data->titleOffset );
00646 break;
00647
00648 case QwtScaleDraw::BottomScale:
00649 angle = 0.0;
00650 flags |= Qt::AlignBottom;
00651 r.setTop( r.top() + d_data->titleOffset );
00652 break;
00653
00654 case QwtScaleDraw::TopScale:
00655 default:
00656 angle = 0.0;
00657 flags |= Qt::AlignTop;
00658 r.setBottom( r.bottom() - d_data->titleOffset );
00659 break;
00660 }
00661
00662 if ( d_data->layoutFlags & TitleInverted )
00663 {
00664 if ( align == QwtScaleDraw::LeftScale
00665 || align == QwtScaleDraw::RightScale )
00666 {
00667 angle = -angle;
00668 r.setRect( r.x() + r.height(), r.y() - r.width(),
00669 r.width(), r.height() );
00670 }
00671 }
00672
00673 painter->save();
00674 painter->setFont( font() );
00675 painter->setPen( palette().color( QPalette::Text ) );
00676
00677 painter->translate( r.x(), r.y() );
00678 if ( angle != 0.0 )
00679 painter->rotate( angle );
00680
00681 QwtText title = d_data->title;
00682 title.setRenderFlags( flags );
00683 title.draw( painter, QRectF( 0.0, 0.0, r.width(), r.height() ) );
00684
00685 painter->restore();
00686 }
00687
00696 void QwtScaleWidget::scaleChange()
00697 {
00698 layoutScale();
00699 }
00700
00704 QSize QwtScaleWidget::sizeHint() const
00705 {
00706 return minimumSizeHint();
00707 }
00708
00712 QSize QwtScaleWidget::minimumSizeHint() const
00713 {
00714 const Qt::Orientation o = d_data->scaleDraw->orientation();
00715
00716
00717
00718 int length = 0;
00719 int mbd1, mbd2;
00720 getBorderDistHint( mbd1, mbd2 );
00721 length += qMax( 0, d_data->borderDist[0] - mbd1 );
00722 length += qMax( 0, d_data->borderDist[1] - mbd2 );
00723 length += d_data->scaleDraw->minLength( font() );
00724
00725 int dim = dimForLength( length, font() );
00726 if ( length < dim )
00727 {
00728
00729 length = dim;
00730 dim = dimForLength( length, font() );
00731 }
00732
00733 QSize size( length + 2, dim );
00734 if ( o == Qt::Vertical )
00735 size.transpose();
00736
00737 int left, right, top, bottom;
00738 getContentsMargins( &left, &top, &right, &bottom );
00739 return size + QSize( left + right, top + bottom );
00740 }
00741
00748 int QwtScaleWidget::titleHeightForWidth( int width ) const
00749 {
00750 return qCeil( d_data->title.heightForWidth( width, font() ) );
00751 }
00752
00762 int QwtScaleWidget::dimForLength( int length, const QFont &scaleFont ) const
00763 {
00764 const int extent = qCeil( d_data->scaleDraw->extent( scaleFont ) );
00765
00766 int dim = d_data->margin + extent + 1;
00767
00768 if ( !d_data->title.isEmpty() )
00769 dim += titleHeightForWidth( length ) + d_data->spacing;
00770
00771 if ( d_data->colorBar.isEnabled && d_data->colorBar.interval.isValid() )
00772 dim += d_data->colorBar.width + d_data->spacing;
00773
00774 return dim;
00775 }
00776
00795 void QwtScaleWidget::getBorderDistHint( int &start, int &end ) const
00796 {
00797 d_data->scaleDraw->getBorderDistHint( font(), start, end );
00798
00799 if ( start < d_data->minBorderDist[0] )
00800 start = d_data->minBorderDist[0];
00801
00802 if ( end < d_data->minBorderDist[1] )
00803 end = d_data->minBorderDist[1];
00804 }
00805
00816 void QwtScaleWidget::setMinBorderDist( int start, int end )
00817 {
00818 d_data->minBorderDist[0] = start;
00819 d_data->minBorderDist[1] = end;
00820 }
00821
00833 void QwtScaleWidget::getMinBorderDist( int &start, int &end ) const
00834 {
00835 start = d_data->minBorderDist[0];
00836 end = d_data->minBorderDist[1];
00837 }
00838
00847 void QwtScaleWidget::setScaleDiv( const QwtScaleDiv &scaleDiv )
00848 {
00849 QwtScaleDraw *sd = d_data->scaleDraw;
00850 if ( sd->scaleDiv() != scaleDiv )
00851 {
00852 sd->setScaleDiv( scaleDiv );
00853 layoutScale();
00854
00855 Q_EMIT scaleDivChanged();
00856 }
00857 }
00858
00865 void QwtScaleWidget::setTransformation( QwtTransform *transformation )
00866 {
00867 d_data->scaleDraw->setTransformation( transformation );
00868 layoutScale();
00869 }
00870
00875 void QwtScaleWidget::setColorBarEnabled( bool on )
00876 {
00877 if ( on != d_data->colorBar.isEnabled )
00878 {
00879 d_data->colorBar.isEnabled = on;
00880 layoutScale();
00881 }
00882 }
00883
00888 bool QwtScaleWidget::isColorBarEnabled() const
00889 {
00890 return d_data->colorBar.isEnabled;
00891 }
00892
00899 void QwtScaleWidget::setColorBarWidth( int width )
00900 {
00901 if ( width != d_data->colorBar.width )
00902 {
00903 d_data->colorBar.width = width;
00904 if ( isColorBarEnabled() )
00905 layoutScale();
00906 }
00907 }
00908
00913 int QwtScaleWidget::colorBarWidth() const
00914 {
00915 return d_data->colorBar.width;
00916 }
00917
00922 QwtInterval QwtScaleWidget::colorBarInterval() const
00923 {
00924 return d_data->colorBar.interval;
00925 }
00926
00936 void QwtScaleWidget::setColorMap(
00937 const QwtInterval &interval, QwtColorMap *colorMap )
00938 {
00939 d_data->colorBar.interval = interval;
00940
00941 if ( colorMap != d_data->colorBar.colorMap )
00942 {
00943 delete d_data->colorBar.colorMap;
00944 d_data->colorBar.colorMap = colorMap;
00945 }
00946
00947 if ( isColorBarEnabled() )
00948 layoutScale();
00949 }
00950
00955 const QwtColorMap *QwtScaleWidget::colorMap() const
00956 {
00957 return d_data->colorBar.colorMap;
00958 }