qwt_scale_widget.cpp

00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
00002  * Qwt Widget Library
00003  * Copyright (C) 1997   Josef Wilgen
00004  * Copyright (C) 2002   Uwe Rathmann
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the Qwt License, Version 1.0
00008  *****************************************************************************/
00009 
00010 // vim: expandtab
00011 
00012 #include <qpainter.h>
00013 #include <qevent.h>
00014 #include "qwt_painter.h"
00015 #include "qwt_color_map.h"
00016 #include "qwt_scale_widget.h"
00017 #include "qwt_scale_map.h"
00018 #include "qwt_math.h"
00019 #include "qwt_paint_buffer.h"
00020 #include "qwt_scale_div.h"
00021 #include "qwt_text.h"
00022 
00023 class QwtScaleWidget::PrivateData
00024 {
00025 public:
00026     PrivateData():
00027         scaleDraw(NULL)
00028     {
00029         colorBar.colorMap = NULL;
00030     }
00031 
00032     ~PrivateData()
00033     {
00034         delete scaleDraw;
00035         delete colorBar.colorMap;
00036     }
00037 
00038     QwtScaleDraw *scaleDraw;
00039 
00040     int borderDist[2];
00041     int minBorderDist[2];
00042     int scaleLength;
00043     int margin;
00044     int penWidth;
00045 
00046     int titleOffset;
00047     int spacing;
00048     QwtText title;
00049 
00050     struct t_colorBar
00051     {
00052         bool isEnabled;
00053         int width;
00054         QwtDoubleInterval interval;
00055         QwtColorMap *colorMap;
00056     } colorBar;
00057 };
00058 
00063 QwtScaleWidget::QwtScaleWidget(QWidget *parent):
00064     QWidget(parent)
00065 {
00066     initScale(QwtScaleDraw::LeftScale);
00067 }
00068 
00069 #if QT_VERSION < 0x040000
00070 
00075 QwtScaleWidget::QwtScaleWidget(QWidget *parent, const char *name):
00076     QWidget(parent, name)
00077 {
00078     initScale(QwtScaleDraw::LeftScale);
00079 }
00080 #endif
00081 
00087 QwtScaleWidget::QwtScaleWidget(
00088         QwtScaleDraw::Alignment align, QWidget *parent):
00089     QWidget(parent)
00090 {
00091     initScale(align);
00092 }
00093 
00095 QwtScaleWidget::~QwtScaleWidget()
00096 {
00097     delete d_data;
00098 }
00099 
00101 void QwtScaleWidget::initScale(QwtScaleDraw::Alignment align)
00102 {
00103     d_data = new PrivateData;
00104 
00105 #if QT_VERSION < 0x040000
00106     setWFlags(Qt::WNoAutoErase);
00107 #endif 
00108 
00109     d_data->borderDist[0] = 0;
00110     d_data->borderDist[1] = 0;
00111     d_data->minBorderDist[0] = 0;
00112     d_data->minBorderDist[1] = 0;
00113     d_data->margin = 4;
00114     d_data->penWidth = 0;
00115     d_data->titleOffset = 0;
00116     d_data->spacing = 2;
00117 
00118     d_data->scaleDraw = new QwtScaleDraw;
00119     d_data->scaleDraw->setAlignment(align);
00120     d_data->scaleDraw->setLength(10);
00121 
00122     d_data->colorBar.colorMap = new QwtLinearColorMap();
00123     d_data->colorBar.isEnabled = false;
00124     d_data->colorBar.width = 10;
00125     
00126     const int flags = Qt::AlignHCenter
00127 #if QT_VERSION < 0x040000
00128         | Qt::WordBreak | Qt::ExpandTabs;
00129 #else
00130         | Qt::TextExpandTabs | Qt::TextWordWrap;
00131 #endif
00132     d_data->title.setRenderFlags(flags); 
00133     d_data->title.setFont(font()); 
00134 
00135     QSizePolicy policy(QSizePolicy::MinimumExpanding,
00136         QSizePolicy::Fixed);
00137     if ( d_data->scaleDraw->orientation() == Qt::Vertical )
00138         policy.transpose();
00139 
00140     setSizePolicy(policy);
00141     
00142 #if QT_VERSION >= 0x040000
00143     setAttribute(Qt::WA_WState_OwnSizePolicy, false);
00144 #else
00145     clearWState( WState_OwnSizePolicy );
00146 #endif
00147 
00148 }
00149 
00150 void QwtScaleWidget::setTitle(const QString &title)
00151 {
00152     if ( d_data->title.text() != title )
00153     {
00154         d_data->title.setText(title);
00155         layoutScale();
00156     }
00157 }
00158 
00167 void QwtScaleWidget::setTitle(const QwtText &title)
00168 {
00169     QwtText t = title;
00170     const int flags = title.renderFlags() & ~(Qt::AlignTop | Qt::AlignBottom);
00171     t.setRenderFlags(flags);
00172 
00173     if (t != d_data->title)
00174     {
00175         d_data->title = t;
00176         layoutScale();
00177     }
00178 }
00179 
00186 void QwtScaleWidget::setAlignment(QwtScaleDraw::Alignment alignment)
00187 {
00188 #if QT_VERSION >= 0x040000
00189     if ( !testAttribute(Qt::WA_WState_OwnSizePolicy) )
00190 #else
00191     if ( !testWState( WState_OwnSizePolicy ) )
00192 #endif
00193     {
00194         QSizePolicy policy(QSizePolicy::MinimumExpanding,
00195             QSizePolicy::Fixed);
00196         if ( d_data->scaleDraw->orientation() == Qt::Vertical )
00197             policy.transpose();
00198         setSizePolicy(policy);
00199 
00200 #if QT_VERSION >= 0x040000
00201         setAttribute(Qt::WA_WState_OwnSizePolicy, false);
00202 #else
00203         clearWState( WState_OwnSizePolicy );
00204 #endif
00205     }
00206 
00207     if (d_data->scaleDraw)
00208         d_data->scaleDraw->setAlignment(alignment);
00209     layoutScale();
00210 }
00211 
00212         
00217 QwtScaleDraw::Alignment QwtScaleWidget::alignment() const 
00218 {
00219     if (!scaleDraw())
00220         return QwtScaleDraw::LeftScale;
00221 
00222     return scaleDraw()->alignment();
00223 }
00224 
00233 void QwtScaleWidget::setBorderDist(int dist1, int dist2)
00234 {
00235     if ( dist1 != d_data->borderDist[0] || dist2 != d_data->borderDist[1] )
00236     {
00237         d_data->borderDist[0] = dist1;
00238         d_data->borderDist[1] = dist2;
00239         layoutScale();
00240     }
00241 }
00242 
00248 void QwtScaleWidget::setMargin(int margin)
00249 {
00250     margin = qwtMax( 0, margin );
00251     if ( margin != d_data->margin )
00252     {
00253         d_data->margin = margin;
00254         layoutScale();
00255     }
00256 }
00257 
00263 void QwtScaleWidget::setSpacing(int spacing)
00264 {
00265     spacing = qwtMax( 0, spacing );
00266     if ( spacing != d_data->spacing )
00267     {
00268         d_data->spacing = spacing;
00269         layoutScale();
00270     }
00271 }
00272 
00278 void QwtScaleWidget::setPenWidth(int width)
00279 {
00280     if ( width < 0 )
00281         width = 0;
00282 
00283     if ( width != d_data->penWidth )
00284     {
00285         d_data->penWidth = width;
00286         layoutScale();
00287     }
00288 }
00289 
00295 #if QT_VERSION < 0x040000
00296 void QwtScaleWidget::setLabelAlignment(int alignment)
00297 #else
00298 void QwtScaleWidget::setLabelAlignment(Qt::Alignment alignment)
00299 #endif
00300 {
00301     d_data->scaleDraw->setLabelAlignment(alignment);
00302     layoutScale();
00303 }
00304 
00310 void QwtScaleWidget::setLabelRotation(double rotation)
00311 {
00312     d_data->scaleDraw->setLabelRotation(rotation);
00313     layoutScale();
00314 }
00315 
00321 void QwtScaleWidget::setScaleDraw(QwtScaleDraw *sd)
00322 {
00323     if ( sd == NULL || sd == d_data->scaleDraw )
00324         return;
00325 
00326     if ( d_data->scaleDraw )
00327         sd->setAlignment(d_data->scaleDraw->alignment());
00328 
00329     delete d_data->scaleDraw;
00330     d_data->scaleDraw = sd;
00331 
00332     layoutScale();
00333 }
00334 
00339 const QwtScaleDraw *QwtScaleWidget::scaleDraw() const 
00340 { 
00341     return d_data->scaleDraw; 
00342 }
00343 
00348 QwtScaleDraw *QwtScaleWidget::scaleDraw() 
00349 { 
00350     return d_data->scaleDraw; 
00351 }
00352 
00357 QwtText QwtScaleWidget::title() const 
00358 {
00359     return d_data->title;
00360 }
00361 
00366 int QwtScaleWidget::startBorderDist() const 
00367 { 
00368     return d_data->borderDist[0]; 
00369 }  
00370 
00375 int QwtScaleWidget::endBorderDist() const 
00376 { 
00377     return d_data->borderDist[1]; 
00378 }
00379 
00384 int QwtScaleWidget::margin() const 
00385 { 
00386     return d_data->margin; 
00387 }
00388 
00393 int QwtScaleWidget::spacing() const 
00394 { 
00395     return d_data->spacing; 
00396 }
00397 
00402 int QwtScaleWidget::penWidth() const
00403 {
00404     return d_data->penWidth;
00405 } 
00409 void QwtScaleWidget::paintEvent(QPaintEvent *e)
00410 {
00411     const QRect &ur = e->rect();
00412     if ( ur.isValid() )
00413     {
00414 #if QT_VERSION < 0x040000
00415         QwtPaintBuffer paintBuffer(this, ur);
00416         draw(paintBuffer.painter());
00417 #else
00418         QPainter painter(this);
00419         draw(&painter);
00420 #endif
00421     }
00422 }
00423 
00427 void QwtScaleWidget::draw(QPainter *painter) const
00428 {
00429     painter->save();
00430 
00431     QPen scalePen = painter->pen();
00432     scalePen.setWidth(d_data->penWidth);
00433     painter->setPen(scalePen);
00434     
00435 #if QT_VERSION < 0x040000
00436     d_data->scaleDraw->draw(painter, colorGroup());
00437 #else
00438     d_data->scaleDraw->draw(painter, palette());
00439 #endif
00440     painter->restore();
00441 
00442     if ( d_data->colorBar.isEnabled && d_data->colorBar.width > 0 &&
00443         d_data->colorBar.interval.isValid() )
00444     {
00445         drawColorBar(painter, colorBarRect(rect()));
00446     }
00447 
00448     QRect r = rect();
00449     if ( d_data->scaleDraw->orientation() == Qt::Horizontal )
00450     {
00451         r.setLeft(r.left() + d_data->borderDist[0]);
00452         r.setWidth(r.width() - d_data->borderDist[1]);
00453     }
00454     else
00455     {
00456         r.setTop(r.top() + d_data->borderDist[0]);
00457         r.setHeight(r.height() - d_data->borderDist[1]);
00458     }
00459 
00460     if ( !d_data->title.isEmpty() )
00461     {
00462         QRect tr = r;
00463         switch(d_data->scaleDraw->alignment())
00464         {
00465             case QwtScaleDraw::LeftScale:
00466                 tr.setRight( r.right() - d_data->titleOffset );
00467                 break;
00468 
00469             case QwtScaleDraw::RightScale:
00470                 tr.setLeft( r.left() + d_data->titleOffset );
00471                 break;
00472 
00473             case QwtScaleDraw::BottomScale:
00474                 tr.setTop( r.top() + d_data->titleOffset );
00475                 break;
00476 
00477             case QwtScaleDraw::TopScale:
00478             default:
00479                 tr.setBottom( r.bottom() - d_data->titleOffset );
00480                 break;
00481         }
00482 
00483         drawTitle(painter, d_data->scaleDraw->alignment(), tr);
00484     }
00485 }
00486 
00487 QRect QwtScaleWidget::colorBarRect(const QRect& rect) const
00488 {
00489     QRect cr = rect;
00490 
00491     if ( d_data->scaleDraw->orientation() == Qt::Horizontal )
00492     {
00493         cr.setLeft(cr.left() + d_data->borderDist[0]);
00494         cr.setWidth(cr.width() - d_data->borderDist[1] + 1);
00495     }
00496     else
00497     {
00498         cr.setTop(cr.top() + d_data->borderDist[0]);
00499         cr.setHeight(cr.height() - d_data->borderDist[1] + 1);
00500     }
00501 
00502     switch(d_data->scaleDraw->alignment())
00503     {
00504         case QwtScaleDraw::LeftScale:
00505         {
00506             cr.setLeft( cr.right() - d_data->spacing 
00507                 - d_data->colorBar.width + 1 );
00508             cr.setWidth(d_data->colorBar.width);
00509             break;
00510         }
00511 
00512         case QwtScaleDraw::RightScale:
00513         {
00514             cr.setLeft( cr.left() + d_data->spacing );
00515             cr.setWidth(d_data->colorBar.width);
00516             break;
00517         }
00518 
00519         case QwtScaleDraw::BottomScale:
00520         {
00521             cr.setTop( cr.top() + d_data->spacing );
00522             cr.setHeight(d_data->colorBar.width);
00523             break;
00524         }
00525 
00526         case QwtScaleDraw::TopScale:
00527         {
00528             cr.setTop( cr.bottom() - d_data->spacing
00529                 - d_data->colorBar.width + 1 );
00530             cr.setHeight(d_data->colorBar.width);
00531             break;
00532         }
00533     }
00534 
00535     return cr;
00536 }
00537 
00541 void QwtScaleWidget::resizeEvent(QResizeEvent *)
00542 {
00543     layoutScale(false);
00544 }
00545 
00547 //  the current rect and fonts.
00548 //  \param update_geometry   notify the layout system and call update
00549 //         to redraw the scale
00550 
00551 void QwtScaleWidget::layoutScale( bool update_geometry )
00552 {
00553     int bd0, bd1;
00554     getBorderDistHint(bd0, bd1);
00555     if ( d_data->borderDist[0] > bd0 )
00556         bd0 = d_data->borderDist[0];
00557     if ( d_data->borderDist[1] > bd1 )
00558         bd1 = d_data->borderDist[1];
00559 
00560     int colorBarWidth = 0;
00561     if ( d_data->colorBar.isEnabled && d_data->colorBar.interval.isValid() )
00562         colorBarWidth = d_data->colorBar.width + d_data->spacing;
00563 
00564     const QRect r = rect();
00565     int x, y, length;
00566 
00567     if ( d_data->scaleDraw->orientation() == Qt::Vertical )
00568     {
00569         y = r.top() + bd0;
00570         length = r.height() - (bd0 + bd1);
00571 
00572         if ( d_data->scaleDraw->alignment() == QwtScaleDraw::LeftScale )
00573             x = r.right() - d_data->margin - colorBarWidth;
00574         else
00575             x = r.left() + d_data->margin + colorBarWidth;
00576     }
00577     else
00578     {
00579         x = r.left() + bd0; 
00580         length = r.width() - (bd0 + bd1);
00581 
00582         if ( d_data->scaleDraw->alignment() == QwtScaleDraw::BottomScale )
00583             y = r.top() + d_data->margin + colorBarWidth;
00584         else
00585             y = r.bottom() - d_data->margin - colorBarWidth;
00586     }
00587 
00588     d_data->scaleDraw->move(x, y);
00589     d_data->scaleDraw->setLength(length);
00590 
00591     d_data->titleOffset = d_data->margin + d_data->spacing +
00592         colorBarWidth +
00593         d_data->scaleDraw->extent(QPen(Qt::black, d_data->penWidth), font());
00594 
00595     if ( update_geometry )
00596     {
00597       updateGeometry();
00598       update();
00599     }
00600 }
00601 
00602 void QwtScaleWidget::drawColorBar(QPainter *painter, const QRect& rect) const
00603 {
00604     if ( !d_data->colorBar.interval.isValid() )
00605         return;
00606 
00607     const QwtScaleDraw* sd = d_data->scaleDraw;
00608 
00609     QwtPainter::drawColorBar(painter, *d_data->colorBar.colorMap, 
00610         d_data->colorBar.interval.normalized(), sd->map(), 
00611         sd->orientation(), rect);
00612 }
00613 
00621 void QwtScaleWidget::drawTitle(QPainter *painter,
00622     QwtScaleDraw::Alignment align, const QRect &rect) const
00623 {
00624     QRect r;
00625     double angle;
00626     int flags = d_data->title.renderFlags() & 
00627         ~(Qt::AlignTop | Qt::AlignBottom | Qt::AlignVCenter);
00628 
00629     switch(align)
00630     {
00631         case QwtScaleDraw::LeftScale:
00632             flags |= Qt::AlignTop;
00633             angle = -90.0;
00634             r.setRect(rect.left(), rect.bottom(), rect.height(), rect.width());
00635             break;
00636         case QwtScaleDraw::RightScale:
00637             flags |= Qt::AlignTop;
00638             angle = 90.0;
00639             r.setRect(rect.right(), rect.top(), rect.height(), rect.width());
00640             break;
00641         case QwtScaleDraw::TopScale:
00642             flags |= Qt::AlignTop;
00643             angle = 0.0;
00644             r = rect;
00645             break;
00646         case QwtScaleDraw::BottomScale:
00647         default:
00648             flags |= Qt::AlignBottom;
00649             angle = 0.0;
00650             r = rect;
00651             break;
00652     }
00653 
00654     painter->save();
00655     painter->setFont(font());
00656 #if QT_VERSION < 0x040000
00657     painter->setPen(colorGroup().color(QColorGroup::Text));
00658 #else
00659     painter->setPen(palette().color(QPalette::Text));
00660 #endif
00661 
00662     painter->translate(r.x(), r.y());
00663     if (angle != 0.0)
00664         painter->rotate(angle);
00665 
00666     QwtText title = d_data->title;
00667     title.setRenderFlags(flags);
00668     title.draw(painter, QRect(0, 0, r.width(), r.height()));
00669 
00670     painter->restore();
00671 }
00672 
00681 void QwtScaleWidget::scaleChange()
00682 {
00683     layoutScale();
00684 }
00685 
00689 QSize QwtScaleWidget::sizeHint() const
00690 {
00691     return minimumSizeHint();
00692 }
00693 
00697 QSize QwtScaleWidget::minimumSizeHint() const
00698 {
00699     const Qt::Orientation o = d_data->scaleDraw->orientation();
00700 
00701     // Border Distance cannot be less than the scale borderDistHint
00702     // Note, the borderDistHint is already included in minHeight/minWidth
00703     int length = 0;
00704     int mbd1, mbd2;
00705     getBorderDistHint(mbd1, mbd2);
00706     length += qwtMax( 0, d_data->borderDist[0] - mbd1 );
00707     length += qwtMax( 0, d_data->borderDist[1] - mbd2 );
00708     length += d_data->scaleDraw->minLength(
00709         QPen(Qt::black, d_data->penWidth), font());
00710 
00711     int dim = dimForLength(length, font());
00712     if ( length < dim )
00713     {
00714         // compensate for long titles
00715         length = dim;
00716         dim = dimForLength(length, font());
00717     }
00718 
00719     QSize size(length + 2, dim);
00720     if ( o == Qt::Vertical )
00721         size.transpose();
00722 
00723     return size;
00724 }
00725 
00732 int QwtScaleWidget::titleHeightForWidth(int width) const
00733 {
00734     return d_data->title.heightForWidth(width, font());
00735 }
00736 
00746 int QwtScaleWidget::dimForLength(int length, const QFont &scaleFont) const
00747 {
00748     int dim = d_data->margin;
00749     dim += d_data->scaleDraw->extent(
00750         QPen(Qt::black, d_data->penWidth), scaleFont);
00751 
00752     if ( !d_data->title.isEmpty() )
00753         dim += titleHeightForWidth(length) + d_data->spacing;
00754 
00755     if ( d_data->colorBar.isEnabled && d_data->colorBar.interval.isValid() )
00756         dim += d_data->colorBar.width + d_data->spacing;
00757 
00758     return dim;
00759 }
00760 
00774 void QwtScaleWidget::getBorderDistHint(int &start, int &end) const
00775 {
00776     d_data->scaleDraw->getBorderDistHint(font(), start, end);
00777 
00778     if ( start < d_data->minBorderDist[0] )
00779         start = d_data->minBorderDist[0];
00780 
00781     if ( end < d_data->minBorderDist[1] )
00782         end = d_data->minBorderDist[1];
00783 }
00784 
00793 void QwtScaleWidget::setMinBorderDist(int start, int end)
00794 {
00795     d_data->minBorderDist[0] = start;
00796     d_data->minBorderDist[1] = end;
00797 }
00798 
00805 void QwtScaleWidget::getMinBorderDist(int &start, int &end) const
00806 {
00807     start = d_data->minBorderDist[0];
00808     end = d_data->minBorderDist[1];
00809 }
00810 
00811 #if QT_VERSION < 0x040000
00812 
00821 void QwtScaleWidget::fontChange(const QFont &oldFont)
00822 {
00823     QWidget::fontChange( oldFont );
00824     layoutScale();
00825 }
00826 
00827 #endif
00828 
00839 void QwtScaleWidget::setScaleDiv(
00840     QwtScaleTransformation *transformation,
00841     const QwtScaleDiv &scaleDiv)
00842 {
00843     QwtScaleDraw *sd = d_data->scaleDraw;
00844     if (sd->scaleDiv() != scaleDiv ||
00845         sd->map().transformation()->type() != transformation->type() )
00846     {
00847         sd->setTransformation(transformation);
00848         sd->setScaleDiv(scaleDiv);
00849         layoutScale();
00850 
00851         emit scaleDivChanged();
00852     }
00853     else
00854         delete transformation;
00855 }
00856 
00857 void QwtScaleWidget::setColorBarEnabled(bool on)
00858 {
00859     if ( on != d_data->colorBar.isEnabled )
00860     {
00861         d_data->colorBar.isEnabled = on;
00862         layoutScale();
00863     }
00864 }
00865 
00866 bool QwtScaleWidget::isColorBarEnabled() const
00867 {
00868     return d_data->colorBar.isEnabled;
00869 }
00870 
00871 
00872 void QwtScaleWidget::setColorBarWidth(int width)
00873 {
00874     if ( width != d_data->colorBar.width )
00875     {
00876         d_data->colorBar.width = width;
00877         if ( isColorBarEnabled() )
00878             layoutScale();
00879     }
00880 }
00881 
00882 int QwtScaleWidget::colorBarWidth() const
00883 {
00884     return d_data->colorBar.width;
00885 }
00886 
00887 QwtDoubleInterval QwtScaleWidget::colorBarInterval() const
00888 {
00889     return d_data->colorBar.interval;
00890 }
00891 
00892 void QwtScaleWidget::setColorMap(const QwtDoubleInterval &interval,
00893     const QwtColorMap &colorMap)
00894 {
00895     d_data->colorBar.interval = interval;
00896 
00897     delete d_data->colorBar.colorMap;
00898     d_data->colorBar.colorMap = colorMap.copy();
00899 
00900     if ( isColorBarEnabled() )
00901         layoutScale();
00902 }
00903 
00904 const QwtColorMap &QwtScaleWidget::colorMap() const
00905 {
00906     return *d_data->colorBar.colorMap;
00907 }

Generated on Sun Mar 22 16:54:08 2009 for Qwt User's Guide by  doxygen 1.5.0