00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
00156 void QwtScaleWidget::setTitle(const QString &title)
00157 {
00158 if ( d_data->title.text() != title )
00159 {
00160 d_data->title.setText(title);
00161 layoutScale();
00162 }
00163 }
00164
00174 void QwtScaleWidget::setTitle(const QwtText &title)
00175 {
00176 QwtText t = title;
00177 const int flags = title.renderFlags() & ~(Qt::AlignTop | Qt::AlignBottom);
00178 t.setRenderFlags(flags);
00179
00180 if (t != d_data->title)
00181 {
00182 d_data->title = t;
00183 layoutScale();
00184 }
00185 }
00186
00193 void QwtScaleWidget::setAlignment(QwtScaleDraw::Alignment alignment)
00194 {
00195 #if QT_VERSION >= 0x040000
00196 if ( !testAttribute(Qt::WA_WState_OwnSizePolicy) )
00197 #else
00198 if ( !testWState( WState_OwnSizePolicy ) )
00199 #endif
00200 {
00201 QSizePolicy policy(QSizePolicy::MinimumExpanding,
00202 QSizePolicy::Fixed);
00203 if ( d_data->scaleDraw->orientation() == Qt::Vertical )
00204 policy.transpose();
00205 setSizePolicy(policy);
00206
00207 #if QT_VERSION >= 0x040000
00208 setAttribute(Qt::WA_WState_OwnSizePolicy, false);
00209 #else
00210 clearWState( WState_OwnSizePolicy );
00211 #endif
00212 }
00213
00214 if (d_data->scaleDraw)
00215 d_data->scaleDraw->setAlignment(alignment);
00216 layoutScale();
00217 }
00218
00219
00224 QwtScaleDraw::Alignment QwtScaleWidget::alignment() const
00225 {
00226 if (!scaleDraw())
00227 return QwtScaleDraw::LeftScale;
00228
00229 return scaleDraw()->alignment();
00230 }
00231
00240 void QwtScaleWidget::setBorderDist(int dist1, int dist2)
00241 {
00242 if ( dist1 != d_data->borderDist[0] || dist2 != d_data->borderDist[1] )
00243 {
00244 d_data->borderDist[0] = dist1;
00245 d_data->borderDist[1] = dist2;
00246 layoutScale();
00247 }
00248 }
00249
00255 void QwtScaleWidget::setMargin(int margin)
00256 {
00257 margin = qwtMax( 0, margin );
00258 if ( margin != d_data->margin )
00259 {
00260 d_data->margin = margin;
00261 layoutScale();
00262 }
00263 }
00264
00270 void QwtScaleWidget::setSpacing(int spacing)
00271 {
00272 spacing = qwtMax( 0, spacing );
00273 if ( spacing != d_data->spacing )
00274 {
00275 d_data->spacing = spacing;
00276 layoutScale();
00277 }
00278 }
00279
00285 void QwtScaleWidget::setPenWidth(int width)
00286 {
00287 if ( width < 0 )
00288 width = 0;
00289
00290 if ( width != d_data->penWidth )
00291 {
00292 d_data->penWidth = width;
00293 layoutScale();
00294 }
00295 }
00296
00302 #if QT_VERSION < 0x040000
00303 void QwtScaleWidget::setLabelAlignment(int alignment)
00304 #else
00305 void QwtScaleWidget::setLabelAlignment(Qt::Alignment alignment)
00306 #endif
00307 {
00308 d_data->scaleDraw->setLabelAlignment(alignment);
00309 layoutScale();
00310 }
00311
00319 void QwtScaleWidget::setLabelRotation(double rotation)
00320 {
00321 d_data->scaleDraw->setLabelRotation(rotation);
00322 layoutScale();
00323 }
00324
00333 void QwtScaleWidget::setScaleDraw(QwtScaleDraw *sd)
00334 {
00335 if ( sd == NULL || sd == d_data->scaleDraw )
00336 return;
00337
00338 if ( d_data->scaleDraw )
00339 sd->setAlignment(d_data->scaleDraw->alignment());
00340
00341 delete d_data->scaleDraw;
00342 d_data->scaleDraw = sd;
00343
00344 layoutScale();
00345 }
00346
00351 const QwtScaleDraw *QwtScaleWidget::scaleDraw() const
00352 {
00353 return d_data->scaleDraw;
00354 }
00355
00360 QwtScaleDraw *QwtScaleWidget::scaleDraw()
00361 {
00362 return d_data->scaleDraw;
00363 }
00364
00369 QwtText QwtScaleWidget::title() const
00370 {
00371 return d_data->title;
00372 }
00373
00378 int QwtScaleWidget::startBorderDist() const
00379 {
00380 return d_data->borderDist[0];
00381 }
00382
00387 int QwtScaleWidget::endBorderDist() const
00388 {
00389 return d_data->borderDist[1];
00390 }
00391
00396 int QwtScaleWidget::margin() const
00397 {
00398 return d_data->margin;
00399 }
00400
00405 int QwtScaleWidget::spacing() const
00406 {
00407 return d_data->spacing;
00408 }
00409
00414 int QwtScaleWidget::penWidth() const
00415 {
00416 return d_data->penWidth;
00417 }
00421 void QwtScaleWidget::paintEvent(QPaintEvent *e)
00422 {
00423 const QRect &ur = e->rect();
00424 if ( ur.isValid() )
00425 {
00426 #if QT_VERSION < 0x040000
00427 QwtPaintBuffer paintBuffer(this, ur);
00428 draw(paintBuffer.painter());
00429 #else
00430 QPainter painter(this);
00431 draw(&painter);
00432 #endif
00433 }
00434 }
00435
00439 void QwtScaleWidget::draw(QPainter *painter) const
00440 {
00441 painter->save();
00442
00443 QPen scalePen = painter->pen();
00444 scalePen.setWidth(d_data->penWidth);
00445 painter->setPen(scalePen);
00446
00447 #if QT_VERSION < 0x040000
00448 d_data->scaleDraw->draw(painter, colorGroup());
00449 #else
00450 d_data->scaleDraw->draw(painter, palette());
00451 #endif
00452 painter->restore();
00453
00454 if ( d_data->colorBar.isEnabled && d_data->colorBar.width > 0 &&
00455 d_data->colorBar.interval.isValid() )
00456 {
00457 drawColorBar(painter, colorBarRect(rect()));
00458 }
00459
00460 QRect r = rect();
00461 if ( d_data->scaleDraw->orientation() == Qt::Horizontal )
00462 {
00463 r.setLeft(r.left() + d_data->borderDist[0]);
00464 r.setWidth(r.width() - d_data->borderDist[1]);
00465 }
00466 else
00467 {
00468 r.setTop(r.top() + d_data->borderDist[0]);
00469 r.setHeight(r.height() - d_data->borderDist[1]);
00470 }
00471
00472 if ( !d_data->title.isEmpty() )
00473 {
00474 QRect tr = r;
00475 switch(d_data->scaleDraw->alignment())
00476 {
00477 case QwtScaleDraw::LeftScale:
00478 tr.setRight( r.right() - d_data->titleOffset );
00479 break;
00480
00481 case QwtScaleDraw::RightScale:
00482 tr.setLeft( r.left() + d_data->titleOffset );
00483 break;
00484
00485 case QwtScaleDraw::BottomScale:
00486 tr.setTop( r.top() + d_data->titleOffset );
00487 break;
00488
00489 case QwtScaleDraw::TopScale:
00490 default:
00491 tr.setBottom( r.bottom() - d_data->titleOffset );
00492 break;
00493 }
00494
00495 drawTitle(painter, d_data->scaleDraw->alignment(), tr);
00496 }
00497 }
00498
00499 QRect QwtScaleWidget::colorBarRect(const QRect& rect) const
00500 {
00501 QRect cr = rect;
00502
00503 if ( d_data->scaleDraw->orientation() == Qt::Horizontal )
00504 {
00505 cr.setLeft(cr.left() + d_data->borderDist[0]);
00506 cr.setWidth(cr.width() - d_data->borderDist[1] + 1);
00507 }
00508 else
00509 {
00510 cr.setTop(cr.top() + d_data->borderDist[0]);
00511 cr.setHeight(cr.height() - d_data->borderDist[1] + 1);
00512 }
00513
00514 switch(d_data->scaleDraw->alignment())
00515 {
00516 case QwtScaleDraw::LeftScale:
00517 {
00518 cr.setLeft( cr.right() - d_data->spacing
00519 - d_data->colorBar.width + 1 );
00520 cr.setWidth(d_data->colorBar.width);
00521 break;
00522 }
00523
00524 case QwtScaleDraw::RightScale:
00525 {
00526 cr.setLeft( cr.left() + d_data->spacing );
00527 cr.setWidth(d_data->colorBar.width);
00528 break;
00529 }
00530
00531 case QwtScaleDraw::BottomScale:
00532 {
00533 cr.setTop( cr.top() + d_data->spacing );
00534 cr.setHeight(d_data->colorBar.width);
00535 break;
00536 }
00537
00538 case QwtScaleDraw::TopScale:
00539 {
00540 cr.setTop( cr.bottom() - d_data->spacing
00541 - d_data->colorBar.width + 1 );
00542 cr.setHeight(d_data->colorBar.width);
00543 break;
00544 }
00545 }
00546
00547 return cr;
00548 }
00549
00553 void QwtScaleWidget::resizeEvent(QResizeEvent *)
00554 {
00555 layoutScale(false);
00556 }
00557
00559
00560
00561
00562
00563 void QwtScaleWidget::layoutScale( bool update_geometry )
00564 {
00565 int bd0, bd1;
00566 getBorderDistHint(bd0, bd1);
00567 if ( d_data->borderDist[0] > bd0 )
00568 bd0 = d_data->borderDist[0];
00569 if ( d_data->borderDist[1] > bd1 )
00570 bd1 = d_data->borderDist[1];
00571
00572 int colorBarWidth = 0;
00573 if ( d_data->colorBar.isEnabled && d_data->colorBar.interval.isValid() )
00574 colorBarWidth = d_data->colorBar.width + d_data->spacing;
00575
00576 const QRect r = rect();
00577 int x, y, length;
00578
00579 if ( d_data->scaleDraw->orientation() == Qt::Vertical )
00580 {
00581 y = r.top() + bd0;
00582 length = r.height() - (bd0 + bd1);
00583
00584 if ( d_data->scaleDraw->alignment() == QwtScaleDraw::LeftScale )
00585 x = r.right() - d_data->margin - colorBarWidth;
00586 else
00587 x = r.left() + d_data->margin + colorBarWidth;
00588 }
00589 else
00590 {
00591 x = r.left() + bd0;
00592 length = r.width() - (bd0 + bd1);
00593
00594 if ( d_data->scaleDraw->alignment() == QwtScaleDraw::BottomScale )
00595 y = r.top() + d_data->margin + colorBarWidth;
00596 else
00597 y = r.bottom() - d_data->margin - colorBarWidth;
00598 }
00599
00600 d_data->scaleDraw->move(x, y);
00601 d_data->scaleDraw->setLength(length);
00602
00603 d_data->titleOffset = d_data->margin + d_data->spacing +
00604 colorBarWidth +
00605 d_data->scaleDraw->extent(QPen(Qt::black, d_data->penWidth), font());
00606
00607 if ( update_geometry )
00608 {
00609 updateGeometry();
00610 update();
00611 }
00612 }
00613
00614 void QwtScaleWidget::drawColorBar(QPainter *painter, const QRect& rect) const
00615 {
00616 if ( !d_data->colorBar.interval.isValid() )
00617 return;
00618
00619 const QwtScaleDraw* sd = d_data->scaleDraw;
00620
00621 QwtPainter::drawColorBar(painter, *d_data->colorBar.colorMap,
00622 d_data->colorBar.interval.normalized(), sd->map(),
00623 sd->orientation(), rect);
00624 }
00625
00633 void QwtScaleWidget::drawTitle(QPainter *painter,
00634 QwtScaleDraw::Alignment align, const QRect &rect) const
00635 {
00636 QRect r;
00637 double angle;
00638 int flags = d_data->title.renderFlags() &
00639 ~(Qt::AlignTop | Qt::AlignBottom | Qt::AlignVCenter);
00640
00641 switch(align)
00642 {
00643 case QwtScaleDraw::LeftScale:
00644 flags |= Qt::AlignTop;
00645 angle = -90.0;
00646 r.setRect(rect.left(), rect.bottom(), rect.height(), rect.width());
00647 break;
00648 case QwtScaleDraw::RightScale:
00649 flags |= Qt::AlignTop;
00650 angle = 90.0;
00651 r.setRect(rect.right(), rect.top(), rect.height(), rect.width());
00652 break;
00653 case QwtScaleDraw::TopScale:
00654 flags |= Qt::AlignTop;
00655 angle = 0.0;
00656 r = rect;
00657 break;
00658 case QwtScaleDraw::BottomScale:
00659 default:
00660 flags |= Qt::AlignBottom;
00661 angle = 0.0;
00662 r = rect;
00663 break;
00664 }
00665
00666 painter->save();
00667 painter->setFont(font());
00668 #if QT_VERSION < 0x040000
00669 painter->setPen(colorGroup().color(QColorGroup::Text));
00670 #else
00671 painter->setPen(palette().color(QPalette::Text));
00672 #endif
00673
00674 const QwtMetricsMap metricsMap = QwtPainter::metricsMap();
00675 QwtPainter::resetMetricsMap();
00676
00677 r = metricsMap.layoutToDevice(r);
00678
00679 painter->translate(r.x(), r.y());
00680 if (angle != 0.0)
00681 painter->rotate(angle);
00682
00683 QwtText title = d_data->title;
00684 title.setRenderFlags(flags);
00685 title.draw(painter, QRect(0, 0, r.width(), r.height()));
00686
00687 QwtPainter::setMetricsMap(metricsMap);
00688
00689 painter->restore();
00690 }
00691
00700 void QwtScaleWidget::scaleChange()
00701 {
00702 layoutScale();
00703 }
00704
00708 QSize QwtScaleWidget::sizeHint() const
00709 {
00710 return minimumSizeHint();
00711 }
00712
00716 QSize QwtScaleWidget::minimumSizeHint() const
00717 {
00718 const Qt::Orientation o = d_data->scaleDraw->orientation();
00719
00720
00721
00722 int length = 0;
00723 int mbd1, mbd2;
00724 getBorderDistHint(mbd1, mbd2);
00725 length += qwtMax( 0, d_data->borderDist[0] - mbd1 );
00726 length += qwtMax( 0, d_data->borderDist[1] - mbd2 );
00727 length += d_data->scaleDraw->minLength(
00728 QPen(Qt::black, d_data->penWidth), font());
00729
00730 int dim = dimForLength(length, font());
00731 if ( length < dim )
00732 {
00733
00734 length = dim;
00735 dim = dimForLength(length, font());
00736 }
00737
00738 QSize size(length + 2, dim);
00739 if ( o == Qt::Vertical )
00740 size.transpose();
00741
00742 return size;
00743 }
00744
00751 int QwtScaleWidget::titleHeightForWidth(int width) const
00752 {
00753 return d_data->title.heightForWidth(width, font());
00754 }
00755
00765 int QwtScaleWidget::dimForLength(int length, const QFont &scaleFont) const
00766 {
00767 int dim = d_data->margin;
00768 dim += d_data->scaleDraw->extent(
00769 QPen(Qt::black, d_data->penWidth), scaleFont);
00770
00771 if ( !d_data->title.isEmpty() )
00772 dim += titleHeightForWidth(length) + d_data->spacing;
00773
00774 if ( d_data->colorBar.isEnabled && d_data->colorBar.interval.isValid() )
00775 dim += d_data->colorBar.width + d_data->spacing;
00776
00777 return dim;
00778 }
00779
00793 void QwtScaleWidget::getBorderDistHint(int &start, int &end) const
00794 {
00795 d_data->scaleDraw->getBorderDistHint(font(), start, end);
00796
00797 if ( start < d_data->minBorderDist[0] )
00798 start = d_data->minBorderDist[0];
00799
00800 if ( end < d_data->minBorderDist[1] )
00801 end = d_data->minBorderDist[1];
00802 }
00803
00814 void QwtScaleWidget::setMinBorderDist(int start, int end)
00815 {
00816 d_data->minBorderDist[0] = start;
00817 d_data->minBorderDist[1] = end;
00818 }
00819
00826 void QwtScaleWidget::getMinBorderDist(int &start, int &end) const
00827 {
00828 start = d_data->minBorderDist[0];
00829 end = d_data->minBorderDist[1];
00830 }
00831
00832 #if QT_VERSION < 0x040000
00833
00842 void QwtScaleWidget::fontChange(const QFont &oldFont)
00843 {
00844 QWidget::fontChange( oldFont );
00845 layoutScale();
00846 }
00847
00848 #endif
00849
00860 void QwtScaleWidget::setScaleDiv(
00861 QwtScaleTransformation *transformation,
00862 const QwtScaleDiv &scaleDiv)
00863 {
00864 QwtScaleDraw *sd = d_data->scaleDraw;
00865 if (sd->scaleDiv() != scaleDiv ||
00866 sd->map().transformation()->type() != transformation->type() )
00867 {
00868 sd->setTransformation(transformation);
00869 sd->setScaleDiv(scaleDiv);
00870 layoutScale();
00871
00872 emit scaleDivChanged();
00873 }
00874 else
00875 delete transformation;
00876 }
00877
00878 void QwtScaleWidget::setColorBarEnabled(bool on)
00879 {
00880 if ( on != d_data->colorBar.isEnabled )
00881 {
00882 d_data->colorBar.isEnabled = on;
00883 layoutScale();
00884 }
00885 }
00886
00887 bool QwtScaleWidget::isColorBarEnabled() const
00888 {
00889 return d_data->colorBar.isEnabled;
00890 }
00891
00892
00893 void QwtScaleWidget::setColorBarWidth(int width)
00894 {
00895 if ( width != d_data->colorBar.width )
00896 {
00897 d_data->colorBar.width = width;
00898 if ( isColorBarEnabled() )
00899 layoutScale();
00900 }
00901 }
00902
00903 int QwtScaleWidget::colorBarWidth() const
00904 {
00905 return d_data->colorBar.width;
00906 }
00907
00908 QwtDoubleInterval QwtScaleWidget::colorBarInterval() const
00909 {
00910 return d_data->colorBar.interval;
00911 }
00912
00913 void QwtScaleWidget::setColorMap(const QwtDoubleInterval &interval,
00914 const QwtColorMap &colorMap)
00915 {
00916 d_data->colorBar.interval = interval;
00917
00918 delete d_data->colorBar.colorMap;
00919 d_data->colorBar.colorMap = colorMap.copy();
00920
00921 if ( isColorBarEnabled() )
00922 layoutScale();
00923 }
00924
00925 const QwtColorMap &QwtScaleWidget::colorMap() const
00926 {
00927 return *d_data->colorBar.colorMap;
00928 }