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

Generated on Mon Feb 26 21:22:38 2007 for Qwt User's Guide by  doxygen 1.4.6