00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <math.h>
00013 #include <qevent.h>
00014 #include <qdrawutil.h>
00015 #include <qpainter.h>
00016 #include "qwt_painter.h"
00017 #include "qwt_paint_buffer.h"
00018 #include "qwt_scale_draw.h"
00019 #include "qwt_scale_map.h"
00020 #include "qwt_slider.h"
00021
00022 class QwtSlider::PrivateData
00023 {
00024 public:
00025 QRect sliderRect;
00026
00027 int thumbLength;
00028 int thumbWidth;
00029 int borderWidth;
00030 int scaleDist;
00031 int xMargin;
00032 int yMargin;
00033
00034 QwtSlider::ScalePos scalePos;
00035 QwtSlider::BGSTYLE bgStyle;
00036
00037
00038
00039
00040
00041
00042 QwtScaleMap map;
00043 mutable QSize sizeHintCache;
00044 };
00045
00064 QwtSlider::QwtSlider(QWidget *parent,
00065 Qt::Orientation orientation, ScalePos scalePos, BGSTYLE bgStyle):
00066 QwtAbstractSlider(orientation, parent)
00067 {
00068 initSlider(orientation, scalePos, bgStyle);
00069 }
00070
00071 #if QT_VERSION < 0x040000
00072
00081 QwtSlider::QwtSlider(QWidget *parent, const char* name):
00082 QwtAbstractSlider(Qt::Horizontal, parent)
00083 {
00084 setName(name);
00085 initSlider(Qt::Horizontal, NoScale, BgTrough);
00086 }
00087 #endif
00088
00089 void QwtSlider::initSlider(Qt::Orientation orientation,
00090 ScalePos scalePos, BGSTYLE bgStyle)
00091 {
00092 if (orientation == Qt::Vertical)
00093 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
00094 else
00095 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
00096
00097 #if QT_VERSION >= 0x040000
00098 setAttribute(Qt::WA_WState_OwnSizePolicy, false);
00099 #else
00100 clearWState( WState_OwnSizePolicy );
00101 #endif
00102
00103
00104 #if QT_VERSION < 0x040000
00105 setWFlags(Qt::WNoAutoErase);
00106 #endif
00107
00108 d_data = new QwtSlider::PrivateData;
00109
00110 d_data->borderWidth = 2;
00111 d_data->scaleDist = 4;
00112 d_data->scalePos = scalePos;
00113 d_data->xMargin = 0;
00114 d_data->yMargin = 0;
00115 d_data->bgStyle = bgStyle;
00116
00117 if (bgStyle == BgSlot)
00118 {
00119 d_data->thumbLength = 16;
00120 d_data->thumbWidth = 30;
00121 }
00122 else
00123 {
00124 d_data->thumbLength = 31;
00125 d_data->thumbWidth = 16;
00126 }
00127
00128 d_data->sliderRect.setRect(0,0,8,8);
00129
00130 QwtScaleDraw::Alignment align;
00131 if ( orientation == Qt::Vertical )
00132 {
00133
00134 if ((d_data->scalePos == BottomScale) || (d_data->scalePos == TopScale))
00135 d_data->scalePos = NoScale;
00136
00137 if (d_data->scalePos == RightScale)
00138 align = QwtScaleDraw::RightScale;
00139 else
00140 align = QwtScaleDraw::LeftScale;
00141 }
00142 else
00143 {
00144
00145 if ((d_data->scalePos == LeftScale) || (d_data->scalePos == RightScale))
00146 d_data->scalePos = NoScale;
00147
00148 if (d_data->scalePos == TopScale)
00149 align = QwtScaleDraw::TopScale;
00150 else
00151 align = QwtScaleDraw::BottomScale;
00152 }
00153
00154 scaleDraw()->setAlignment(align);
00155 scaleDraw()->setLength(100);
00156
00157 setRange(0.0, 100.0, 1.0);
00158 setValue(0.0);
00159 }
00160
00161 QwtSlider::~QwtSlider()
00162 {
00163 delete d_data;
00164 }
00165
00174 void QwtSlider::setOrientation(Qt::Orientation o)
00175 {
00176 if ( o == orientation() )
00177 return;
00178
00179 if (o == Qt::Horizontal)
00180 {
00181 if ((d_data->scalePos == LeftScale) || (d_data->scalePos == RightScale))
00182 d_data->scalePos = NoScale;
00183 }
00184 else
00185 {
00186 if ((d_data->scalePos == BottomScale) || (d_data->scalePos == TopScale))
00187 d_data->scalePos = NoScale;
00188 }
00189
00190 #if QT_VERSION >= 0x040000
00191 if ( !testAttribute(Qt::WA_WState_OwnSizePolicy) )
00192 #else
00193 if ( !testWState( WState_OwnSizePolicy ) )
00194 #endif
00195 {
00196 QSizePolicy sp = sizePolicy();
00197 sp.transpose();
00198 setSizePolicy(sp);
00199
00200 #if QT_VERSION >= 0x040000
00201 setAttribute(Qt::WA_WState_OwnSizePolicy, false);
00202 #else
00203 clearWState( WState_OwnSizePolicy );
00204 #endif
00205 }
00206
00207 QwtAbstractSlider::setOrientation(o);
00208 layoutSlider();
00209 }
00210
00224 void QwtSlider::setScalePosition(ScalePos s)
00225 {
00226 if ( d_data->scalePos == s )
00227 return;
00228
00229 d_data->scalePos = s;
00230
00231 switch(d_data->scalePos)
00232 {
00233 case BottomScale:
00234 {
00235 setOrientation(Qt::Horizontal);
00236 scaleDraw()->setAlignment(QwtScaleDraw::BottomScale);
00237 break;
00238 }
00239 case TopScale:
00240 {
00241 setOrientation(Qt::Horizontal);
00242 scaleDraw()->setAlignment(QwtScaleDraw::TopScale);
00243 break;
00244 }
00245 case LeftScale:
00246 {
00247 setOrientation(Qt::Vertical);
00248 scaleDraw()->setAlignment(QwtScaleDraw::LeftScale);
00249 break;
00250 }
00251 case RightScale:
00252 {
00253 setOrientation(Qt::Vertical);
00254 scaleDraw()->setAlignment(QwtScaleDraw::RightScale);
00255 break;
00256 }
00257 default:
00258 {
00259
00260 }
00261 }
00262
00263 layoutSlider();
00264 }
00265
00267 QwtSlider::ScalePos QwtSlider::scalePosition() const
00268 {
00269 return d_data->scalePos;
00270 }
00271
00276 void QwtSlider::setBorderWidth(int bd)
00277 {
00278 if ( bd < 0 )
00279 bd = 0;
00280
00281 if ( bd != d_data->borderWidth )
00282 {
00283 d_data->borderWidth = bd;
00284 layoutSlider();
00285 }
00286 }
00287
00292 void QwtSlider::setThumbLength(int thumbLength)
00293 {
00294 if ( thumbLength < 8 )
00295 thumbLength = 8;
00296
00297 if ( thumbLength != d_data->thumbLength )
00298 {
00299 d_data->thumbLength = thumbLength;
00300 layoutSlider();
00301 }
00302 }
00303
00308 void QwtSlider::setThumbWidth(int w)
00309 {
00310 if ( w < 4 )
00311 w = 4;
00312
00313 if ( d_data->thumbWidth != w )
00314 {
00315 d_data->thumbWidth = w;
00316 layoutSlider();
00317 }
00318 }
00319
00331 void QwtSlider::setScaleDraw(QwtScaleDraw *scaleDraw)
00332 {
00333 const QwtScaleDraw *previousScaleDraw = this->scaleDraw();
00334 if ( scaleDraw == NULL || scaleDraw == previousScaleDraw )
00335 return;
00336
00337 if ( previousScaleDraw )
00338 scaleDraw->setAlignment(previousScaleDraw->alignment());
00339
00340 setAbstractScaleDraw(scaleDraw);
00341 layoutSlider();
00342 }
00343
00348 const QwtScaleDraw *QwtSlider::scaleDraw() const
00349 {
00350 return (QwtScaleDraw *)abstractScaleDraw();
00351 }
00352
00357 QwtScaleDraw *QwtSlider::scaleDraw()
00358 {
00359 return (QwtScaleDraw *)abstractScaleDraw();
00360 }
00361
00363 void QwtSlider::scaleChange()
00364 {
00365 layoutSlider();
00366 }
00367
00368
00370 void QwtSlider::fontChange(const QFont &f)
00371 {
00372 QwtAbstractSlider::fontChange( f );
00373 layoutSlider();
00374 }
00375
00382 void QwtSlider::drawSlider(QPainter *painter, const QRect &r)
00383 {
00384 QRect cr(r);
00385
00386 if (d_data->bgStyle & BgTrough)
00387 {
00388 qDrawShadePanel(painter, r.x(), r.y(),
00389 r.width(), r.height(),
00390 #if QT_VERSION < 0x040000
00391 colorGroup(),
00392 #else
00393 palette(),
00394 #endif
00395 true, d_data->borderWidth,0);
00396
00397 cr.setRect(r.x() + d_data->borderWidth,
00398 r.y() + d_data->borderWidth,
00399 r.width() - 2 * d_data->borderWidth,
00400 r.height() - 2 * d_data->borderWidth);
00401
00402 painter->fillRect(cr.x(), cr.y(), cr.width(), cr.height(),
00403 #if QT_VERSION < 0x040000
00404 colorGroup().brush(QColorGroup::Mid)
00405 #else
00406 palette().brush(QPalette::Mid)
00407 #endif
00408 );
00409 }
00410
00411 if ( d_data->bgStyle & BgSlot)
00412 {
00413 int ws = 4;
00414 int ds = d_data->thumbLength / 2 - 4;
00415 if ( ds < 1 )
00416 ds = 1;
00417
00418 QRect rSlot;
00419 if (orientation() == Qt::Horizontal)
00420 {
00421 if ( cr.height() & 1 )
00422 ws++;
00423 rSlot = QRect(cr.x() + ds,
00424 cr.y() + (cr.height() - ws) / 2,
00425 cr.width() - 2 * ds, ws);
00426 }
00427 else
00428 {
00429 if ( cr.width() & 1 )
00430 ws++;
00431 rSlot = QRect(cr.x() + (cr.width() - ws) / 2,
00432 cr.y() + ds,
00433 ws, cr.height() - 2 * ds);
00434 }
00435 painter->fillRect(rSlot.x(), rSlot.y(), rSlot.width(), rSlot.height(),
00436 #if QT_VERSION < 0x040000
00437 colorGroup().brush(QColorGroup::Dark)
00438 #else
00439 palette().brush(QPalette::Dark)
00440 #endif
00441 );
00442 qDrawShadePanel(painter, rSlot.x(), rSlot.y(),
00443 rSlot.width(), rSlot.height(),
00444 #if QT_VERSION < 0x040000
00445 colorGroup(),
00446 #else
00447 palette(),
00448 #endif
00449 true, 1 ,0);
00450
00451 }
00452
00453 if ( isValid() )
00454 drawThumb(painter, cr, xyPosition(value()));
00455 }
00456
00464 void QwtSlider::drawThumb(QPainter *painter, const QRect &sliderRect, int pos)
00465 {
00466 pos++;
00467 if (orientation() == Qt::Horizontal)
00468 {
00469 qDrawShadePanel(painter, pos - d_data->thumbLength / 2,
00470 sliderRect.y(), d_data->thumbLength, sliderRect.height(),
00471 #if QT_VERSION < 0x040000
00472 colorGroup(),
00473 #else
00474 palette(),
00475 #endif
00476 false, d_data->borderWidth,
00477 #if QT_VERSION < 0x040000
00478 &colorGroup().brush(QColorGroup::Button)
00479 #else
00480 &palette().brush(QPalette::Button)
00481 #endif
00482 );
00483
00484 qDrawShadeLine(painter, pos, sliderRect.y(),
00485 pos, sliderRect.y() + sliderRect.height() - 2,
00486 #if QT_VERSION < 0x040000
00487 colorGroup(),
00488 #else
00489 palette(),
00490 #endif
00491 true, 1);
00492 }
00493 else
00494 {
00495 qDrawShadePanel(painter, sliderRect.x(), pos - d_data->thumbLength / 2,
00496 sliderRect.width(), d_data->thumbLength,
00497 #if QT_VERSION < 0x040000
00498 colorGroup(),
00499 #else
00500 palette(),
00501 #endif
00502 false, d_data->borderWidth,
00503 #if QT_VERSION < 0x040000
00504 &colorGroup().brush(QColorGroup::Button)
00505 #else
00506 &palette().brush(QPalette::Button)
00507 #endif
00508 );
00509
00510 qDrawShadeLine(painter, sliderRect.x(), pos,
00511 sliderRect.x() + sliderRect.width() - 2, pos,
00512 #if QT_VERSION < 0x040000
00513 colorGroup(),
00514 #else
00515 palette(),
00516 #endif
00517 true, 1);
00518 }
00519 }
00520
00525 int QwtSlider::xyPosition(double value) const
00526 {
00527 return d_data->map.transform(value);
00528 }
00529
00534 double QwtSlider::getValue(const QPoint &pos)
00535 {
00536 return d_data->map.invTransform(
00537 orientation() == Qt::Horizontal ? pos.x() : pos.y());
00538 }
00539
00546 void QwtSlider::getScrollMode(const QPoint &p,
00547 int &scrollMode, int &direction )
00548 {
00549 if (!d_data->sliderRect.contains(p))
00550 {
00551 scrollMode = ScrNone;
00552 direction = 0;
00553 return;
00554 }
00555
00556 const int pos = ( orientation() == Qt::Horizontal ) ? p.x() : p.y();
00557 const int markerPos = xyPosition(value());
00558
00559 if ((pos > markerPos - d_data->thumbLength / 2)
00560 && (pos < markerPos + d_data->thumbLength / 2))
00561 {
00562 scrollMode = ScrMouse;
00563 direction = 0;
00564 return;
00565 }
00566
00567 scrollMode = ScrPage;
00568 direction = (pos > markerPos) ? 1 : -1;
00569
00570 if ( scaleDraw()->map().p1() > scaleDraw()->map().p2() )
00571 direction = -direction;
00572 }
00573
00578 void QwtSlider::paintEvent(QPaintEvent *event)
00579 {
00580 const QRect &ur = event->rect();
00581 if ( ur.isValid() )
00582 {
00583 #if QT_VERSION < 0x040000
00584 QwtPaintBuffer paintBuffer(this, ur);
00585 draw(paintBuffer.painter(), ur);
00586 #else
00587 QPainter painter(this);
00588 draw(&painter, ur);
00589 #endif
00590 }
00591 }
00592
00594 void QwtSlider::draw(QPainter *painter, const QRect&)
00595 {
00596 if (d_data->scalePos != NoScale)
00597 {
00598 #if QT_VERSION < 0x040000
00599 scaleDraw()->draw(painter, colorGroup());
00600 #else
00601 scaleDraw()->draw(painter, palette());
00602 #endif
00603 }
00604
00605 drawSlider(painter, d_data->sliderRect);
00606
00607 if ( hasFocus() )
00608 QwtPainter::drawFocusRect(painter, this, d_data->sliderRect);
00609 }
00610
00612 void QwtSlider::resizeEvent(QResizeEvent *)
00613 {
00614 layoutSlider( false );
00615 }
00616
00623 void QwtSlider::layoutSlider( bool update_geometry )
00624 {
00625 int sliderWidth = d_data->thumbWidth;
00626 int sld1 = d_data->thumbLength / 2 - 1;
00627 int sld2 = d_data->thumbLength / 2 + d_data->thumbLength % 2;
00628 if ( d_data->bgStyle & BgTrough )
00629 {
00630 sliderWidth += 2 * d_data->borderWidth;
00631 sld1 += d_data->borderWidth;
00632 sld2 += d_data->borderWidth;
00633 }
00634
00635 int scd = 0;
00636 if ( d_data->scalePos != NoScale )
00637 {
00638 int d1, d2;
00639 scaleDraw()->getBorderDistHint(font(), d1, d2);
00640 scd = qwtMax(d1, d2);
00641 }
00642
00643 int slo = scd - sld1;
00644 if ( slo < 0 )
00645 slo = 0;
00646
00647 int x, y, length;
00648
00649 const QRect r = rect();
00650 if (orientation() == Qt::Horizontal)
00651 {
00652 switch (d_data->scalePos)
00653 {
00654 case TopScale:
00655 {
00656 d_data->sliderRect.setRect(
00657 r.x() + d_data->xMargin + slo,
00658 r.y() + r.height() -
00659 d_data->yMargin - sliderWidth,
00660 r.width() - 2 * d_data->xMargin - 2 * slo,
00661 sliderWidth);
00662
00663 x = d_data->sliderRect.x() + sld1;
00664 y = d_data->sliderRect.y() - d_data->scaleDist;
00665
00666 break;
00667 }
00668
00669 case BottomScale:
00670 {
00671 d_data->sliderRect.setRect(
00672 r.x() + d_data->xMargin + slo,
00673 r.y() + d_data->yMargin,
00674 r.width() - 2 * d_data->xMargin - 2 * slo,
00675 sliderWidth);
00676
00677 x = d_data->sliderRect.x() + sld1;
00678 y = d_data->sliderRect.y() + d_data->sliderRect.height()
00679 + d_data->scaleDist;
00680
00681 break;
00682 }
00683
00684 case NoScale:
00685 default:
00686 {
00687 d_data->sliderRect.setRect(
00688 r.x() + d_data->xMargin + slo,
00689 r.y() + d_data->yMargin,
00690 r.width() - 2 * d_data->xMargin - 2 * slo,
00691 sliderWidth);
00692
00693 x = d_data->sliderRect.x() + sld1;
00694 y = 0;
00695
00696 break;
00697 }
00698 }
00699 length = d_data->sliderRect.width() - (sld1 + sld2);
00700 }
00701 else
00702 {
00703 switch (d_data->scalePos)
00704 {
00705 case RightScale:
00706 d_data->sliderRect.setRect(
00707 r.x() + d_data->xMargin,
00708 r.y() + d_data->yMargin + slo,
00709 sliderWidth,
00710 r.height() - 2 * d_data->yMargin - 2 * slo);
00711
00712 x = d_data->sliderRect.x() + d_data->sliderRect.width()
00713 + d_data->scaleDist;
00714 y = d_data->sliderRect.y() + sld1;
00715
00716 break;
00717
00718 case LeftScale:
00719 d_data->sliderRect.setRect(
00720 r.x() + r.width() - sliderWidth - d_data->xMargin,
00721 r.y() + d_data->yMargin + slo,
00722 sliderWidth,
00723 r.height() - 2 * d_data->yMargin - 2 * slo);
00724
00725 x = d_data->sliderRect.x() - d_data->scaleDist;
00726 y = d_data->sliderRect.y() + sld1;
00727
00728 break;
00729
00730 case NoScale:
00731 default:
00732 d_data->sliderRect.setRect(
00733 r.x() + r.width() - sliderWidth - d_data->xMargin,
00734 r.y() + d_data->yMargin + slo,
00735 sliderWidth,
00736 r.height() - 2 * d_data->yMargin - 2 * slo);
00737
00738 x = 0;
00739 y = d_data->sliderRect.y() + sld1;
00740
00741 break;
00742 }
00743 length = d_data->sliderRect.height() - (sld1 + sld2);
00744 }
00745
00746 scaleDraw()->move(x, y);
00747 scaleDraw()->setLength(length);
00748
00749 d_data->map.setPaintXInterval(scaleDraw()->map().p1(),
00750 scaleDraw()->map().p2());
00751
00752 if ( update_geometry )
00753 {
00754 d_data->sizeHintCache = QSize();
00755 updateGeometry();
00756 update();
00757 }
00758 }
00759
00761 void QwtSlider::valueChange()
00762 {
00763 QwtAbstractSlider::valueChange();
00764 update();
00765 }
00766
00767
00769 void QwtSlider::rangeChange()
00770 {
00771 d_data->map.setScaleInterval(minValue(), maxValue());
00772
00773 if (autoScale())
00774 rescale(minValue(), maxValue());
00775
00776 QwtAbstractSlider::rangeChange();
00777 layoutSlider();
00778 }
00779
00785 void QwtSlider::setMargins(int xMargin, int yMargin)
00786 {
00787 if ( xMargin < 0 )
00788 xMargin = 0;
00789 if ( yMargin < 0 )
00790 yMargin = 0;
00791
00792 if ( xMargin != d_data->xMargin || yMargin != d_data->yMargin )
00793 {
00794 d_data->xMargin = xMargin;
00795 d_data->yMargin = yMargin;
00796 layoutSlider();
00797 }
00798 }
00799
00803 void QwtSlider::setBgStyle(BGSTYLE st)
00804 {
00805 d_data->bgStyle = st;
00806 layoutSlider();
00807 }
00808
00812 QwtSlider::BGSTYLE QwtSlider::bgStyle() const
00813 {
00814 return d_data->bgStyle;
00815 }
00816
00820 int QwtSlider::thumbLength() const
00821 {
00822 return d_data->thumbLength;
00823 }
00824
00828 int QwtSlider::thumbWidth() const
00829 {
00830 return d_data->thumbWidth;
00831 }
00832
00836 int QwtSlider::borderWidth() const
00837 {
00838 return d_data->borderWidth;
00839 }
00840
00844 QSize QwtSlider::sizeHint() const
00845 {
00846 return minimumSizeHint();
00847 }
00848
00854 QSize QwtSlider::minimumSizeHint() const
00855 {
00856 if (!d_data->sizeHintCache.isEmpty())
00857 return d_data->sizeHintCache;
00858
00859 int sliderWidth = d_data->thumbWidth;
00860 if (d_data->bgStyle & BgTrough)
00861 sliderWidth += 2 * d_data->borderWidth;
00862
00863 int w = 0, h = 0;
00864 if (d_data->scalePos != NoScale)
00865 {
00866 int d1, d2;
00867 scaleDraw()->getBorderDistHint(font(), d1, d2);
00868 int msMbd = qwtMax(d1, d2);
00869
00870 int mbd = d_data->thumbLength / 2;
00871 if (d_data->bgStyle & BgTrough)
00872 mbd += d_data->borderWidth;
00873
00874 if ( mbd < msMbd )
00875 mbd = msMbd;
00876
00877 const int sdExtent = scaleDraw()->extent( QPen(), font() );
00878 const int sdLength = scaleDraw()->minLength( QPen(), font() );
00879
00880 h = sliderWidth + sdExtent + d_data->scaleDist;
00881 w = sdLength - 2 * msMbd + 2 * mbd;
00882 }
00883 else
00884 {
00885 w = 200;
00886 h = sliderWidth;
00887 }
00888
00889 if ( orientation() == Qt::Vertical )
00890 qSwap(w, h);
00891
00892 w += 2 * d_data->xMargin;
00893 h += 2 * d_data->yMargin;
00894
00895 d_data->sizeHintCache = QSize(w, h);
00896 return d_data->sizeHintCache;
00897 }