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
00320 void QwtSlider::setScaleDraw(QwtScaleDraw *scaleDraw)
00321 {
00322 setAbstractScaleDraw(scaleDraw);
00323 }
00324
00325 const QwtScaleDraw *QwtSlider::scaleDraw() const
00326 {
00327 return (QwtScaleDraw *)abstractScaleDraw();
00328 }
00329
00330 QwtScaleDraw *QwtSlider::scaleDraw()
00331 {
00332 return (QwtScaleDraw *)abstractScaleDraw();
00333 }
00334
00336 void QwtSlider::scaleChange()
00337 {
00338 layoutSlider();
00339 }
00340
00341
00343 void QwtSlider::fontChange(const QFont &f)
00344 {
00345 QwtAbstractSlider::fontChange( f );
00346 layoutSlider();
00347 }
00348
00350 void QwtSlider::drawSlider(QPainter *p, const QRect &r)
00351 {
00352 QRect cr(r);
00353
00354 if (d_data->bgStyle & BgTrough)
00355 {
00356 qDrawShadePanel(p, r.x(), r.y(),
00357 r.width(), r.height(),
00358 #if QT_VERSION < 0x040000
00359 colorGroup(),
00360 #else
00361 palette(),
00362 #endif
00363 true, d_data->borderWidth,0);
00364
00365 cr.setRect(r.x() + d_data->borderWidth,
00366 r.y() + d_data->borderWidth,
00367 r.width() - 2 * d_data->borderWidth,
00368 r.height() - 2 * d_data->borderWidth);
00369
00370 p->fillRect(cr.x(), cr.y(), cr.width(), cr.height(),
00371 #if QT_VERSION < 0x040000
00372 colorGroup().brush(QColorGroup::Mid)
00373 #else
00374 palette().brush(QPalette::Mid)
00375 #endif
00376 );
00377 }
00378
00379 if ( d_data->bgStyle & BgSlot)
00380 {
00381 int ws = 4;
00382 int ds = d_data->thumbLength / 2 - 4;
00383 if ( ds < 1 )
00384 ds = 1;
00385
00386 QRect rSlot;
00387 if (orientation() == Qt::Horizontal)
00388 {
00389 if ( cr.height() & 1 )
00390 ws++;
00391 rSlot = QRect(cr.x() + ds,
00392 cr.y() + (cr.height() - ws) / 2,
00393 cr.width() - 2 * ds, ws);
00394 }
00395 else
00396 {
00397 if ( cr.width() & 1 )
00398 ws++;
00399 rSlot = QRect(cr.x() + (cr.width() - ws) / 2,
00400 cr.y() + ds,
00401 ws, cr.height() - 2 * ds);
00402 }
00403 p->fillRect(rSlot.x(), rSlot.y(), rSlot.width(), rSlot.height(),
00404 #if QT_VERSION < 0x040000
00405 colorGroup().brush(QColorGroup::Dark)
00406 #else
00407 palette().brush(QPalette::Dark)
00408 #endif
00409 );
00410 qDrawShadePanel(p, rSlot.x(), rSlot.y(),
00411 rSlot.width(), rSlot.height(),
00412 #if QT_VERSION < 0x040000
00413 colorGroup(),
00414 #else
00415 palette(),
00416 #endif
00417 true, 1 ,0);
00418
00419 }
00420
00421 if ( isValid() )
00422 drawThumb(p, cr, xyPosition(value()));
00423 }
00424
00426 void QwtSlider::drawThumb(QPainter *p, const QRect &sliderRect, int pos)
00427 {
00428 pos++;
00429 if (orientation() == Qt::Horizontal)
00430 {
00431 qDrawShadePanel(p, pos - d_data->thumbLength / 2,
00432 sliderRect.y(), d_data->thumbLength, sliderRect.height(),
00433 #if QT_VERSION < 0x040000
00434 colorGroup(),
00435 #else
00436 palette(),
00437 #endif
00438 false, d_data->borderWidth,
00439 #if QT_VERSION < 0x040000
00440 &colorGroup().brush(QColorGroup::Button)
00441 #else
00442 &palette().brush(QPalette::Button)
00443 #endif
00444 );
00445
00446 qDrawShadeLine(p, pos, sliderRect.y(),
00447 pos, sliderRect.y() + sliderRect.height() - 2,
00448 #if QT_VERSION < 0x040000
00449 colorGroup(),
00450 #else
00451 palette(),
00452 #endif
00453 true, 1);
00454 }
00455 else
00456 {
00457 qDrawShadePanel(p,sliderRect.x(), pos - d_data->thumbLength / 2,
00458 sliderRect.width(), d_data->thumbLength,
00459 #if QT_VERSION < 0x040000
00460 colorGroup(),
00461 #else
00462 palette(),
00463 #endif
00464 false, d_data->borderWidth,
00465 #if QT_VERSION < 0x040000
00466 &colorGroup().brush(QColorGroup::Button)
00467 #else
00468 &palette().brush(QPalette::Button)
00469 #endif
00470 );
00471
00472 qDrawShadeLine(p, sliderRect.x(), pos,
00473 sliderRect.x() + sliderRect.width() - 2, pos,
00474 #if QT_VERSION < 0x040000
00475 colorGroup(),
00476 #else
00477 palette(),
00478 #endif
00479 true, 1);
00480 }
00481 }
00482
00484 int QwtSlider::xyPosition(double v) const
00485 {
00486 return d_data->map.transform(v);
00487 }
00488
00490 double QwtSlider::getValue(const QPoint &p)
00491 {
00492 return d_data->map.invTransform(
00493 orientation() == Qt::Horizontal ? p.x() : p.y());
00494 }
00495
00496
00503 void QwtSlider::getScrollMode(const QPoint &p,
00504 int &scrollMode, int &direction )
00505 {
00506 if (!d_data->sliderRect.contains(p))
00507 {
00508 scrollMode = ScrNone;
00509 direction = 0;
00510 return;
00511 }
00512
00513 const int pos = ( orientation() == Qt::Horizontal ) ? p.x() : p.y();
00514 const int markerPos = xyPosition(value());
00515
00516 if ((pos > markerPos - d_data->thumbLength / 2)
00517 && (pos < markerPos + d_data->thumbLength / 2))
00518 {
00519 scrollMode = ScrMouse;
00520 direction = 0;
00521 return;
00522 }
00523
00524 scrollMode = ScrPage;
00525 direction = (pos > markerPos) ? 1 : -1;
00526
00527 if ( scaleDraw()->map().p1() > scaleDraw()->map().p2() )
00528 direction = -direction;
00529 }
00530
00532 void QwtSlider::paintEvent(QPaintEvent *e)
00533 {
00534 const QRect &ur = e->rect();
00535 if ( ur.isValid() )
00536 {
00537 #if QT_VERSION < 0x040000
00538 QwtPaintBuffer paintBuffer(this, ur);
00539 draw(paintBuffer.painter(), ur);
00540 #else
00541 QPainter painter(this);
00542 draw(&painter, ur);
00543 #endif
00544 }
00545 }
00546
00548 void QwtSlider::draw(QPainter *painter, const QRect&)
00549 {
00550 if (d_data->scalePos != NoScale)
00551 {
00552 #if QT_VERSION < 0x040000
00553 scaleDraw()->draw(painter, colorGroup());
00554 #else
00555 scaleDraw()->draw(painter, palette());
00556 #endif
00557 }
00558
00559 drawSlider(painter, d_data->sliderRect);
00560
00561 if ( hasFocus() )
00562 QwtPainter::drawFocusRect(painter, this, d_data->sliderRect);
00563 }
00564
00566 void QwtSlider::resizeEvent(QResizeEvent *)
00567 {
00568 layoutSlider( false );
00569 }
00570
00577 void QwtSlider::layoutSlider( bool update_geometry )
00578 {
00579 int sliderWidth = d_data->thumbWidth;
00580 int sld1 = d_data->thumbLength / 2 - 1;
00581 int sld2 = d_data->thumbLength / 2 + d_data->thumbLength % 2;
00582 if ( d_data->bgStyle & BgTrough )
00583 {
00584 sliderWidth += 2 * d_data->borderWidth;
00585 sld1 += d_data->borderWidth;
00586 sld2 += d_data->borderWidth;
00587 }
00588
00589 int scd = 0;
00590 if ( d_data->scalePos != NoScale )
00591 {
00592 int d1, d2;
00593 scaleDraw()->getBorderDistHint(font(), d1, d2);
00594 scd = qwtMax(d1, d2);
00595 }
00596
00597 int slo = scd - sld1;
00598 if ( slo < 0 )
00599 slo = 0;
00600
00601 int x, y, length;
00602
00603 const QRect r = rect();
00604 if (orientation() == Qt::Horizontal)
00605 {
00606 switch (d_data->scalePos)
00607 {
00608 case TopScale:
00609 {
00610 d_data->sliderRect.setRect(
00611 r.x() + d_data->xMargin + slo,
00612 r.y() + r.height() -
00613 d_data->yMargin - sliderWidth,
00614 r.width() - 2 * d_data->xMargin - 2 * slo,
00615 sliderWidth);
00616
00617 x = d_data->sliderRect.x() + sld1;
00618 y = d_data->sliderRect.y() - d_data->scaleDist;
00619
00620 break;
00621 }
00622
00623 case BottomScale:
00624 {
00625 d_data->sliderRect.setRect(
00626 r.x() + d_data->xMargin + slo,
00627 r.y() + d_data->yMargin,
00628 r.width() - 2 * d_data->xMargin - 2 * slo,
00629 sliderWidth);
00630
00631 x = d_data->sliderRect.x() + sld1;
00632 y = d_data->sliderRect.y() + d_data->sliderRect.height()
00633 + d_data->scaleDist;
00634
00635 break;
00636 }
00637
00638 case NoScale:
00639 default:
00640 {
00641 d_data->sliderRect.setRect(
00642 r.x() + d_data->xMargin + slo,
00643 r.y() + d_data->yMargin,
00644 r.width() - 2 * d_data->xMargin - 2 * slo,
00645 sliderWidth);
00646
00647 x = d_data->sliderRect.x() + sld1;
00648 y = 0;
00649
00650 break;
00651 }
00652 }
00653 length = d_data->sliderRect.width() - (sld1 + sld2);
00654 }
00655 else
00656 {
00657 switch (d_data->scalePos)
00658 {
00659 case RightScale:
00660 d_data->sliderRect.setRect(
00661 r.x() + d_data->xMargin,
00662 r.y() + d_data->yMargin + slo,
00663 sliderWidth,
00664 r.height() - 2 * d_data->yMargin - 2 * slo);
00665
00666 x = d_data->sliderRect.x() + d_data->sliderRect.width()
00667 + d_data->scaleDist;
00668 y = d_data->sliderRect.y() + sld1;
00669
00670 break;
00671
00672 case LeftScale:
00673 d_data->sliderRect.setRect(
00674 r.x() + r.width() - sliderWidth - d_data->xMargin,
00675 r.y() + d_data->yMargin + slo,
00676 sliderWidth,
00677 r.height() - 2 * d_data->yMargin - 2 * slo);
00678
00679 x = d_data->sliderRect.x() - d_data->scaleDist;
00680 y = d_data->sliderRect.y() + sld1;
00681
00682 break;
00683
00684 case NoScale:
00685 default:
00686 d_data->sliderRect.setRect(
00687 r.x() + r.width() - sliderWidth - d_data->xMargin,
00688 r.y() + d_data->yMargin + slo,
00689 sliderWidth,
00690 r.height() - 2 * d_data->yMargin - 2 * slo);
00691
00692 x = 0;
00693 y = d_data->sliderRect.y() + sld1;
00694
00695 break;
00696 }
00697 length = d_data->sliderRect.height() - (sld1 + sld2);
00698 }
00699
00700 scaleDraw()->move(x, y);
00701 scaleDraw()->setLength(length);
00702
00703 d_data->map.setPaintXInterval(scaleDraw()->map().p1(),
00704 scaleDraw()->map().p2());
00705
00706 if ( update_geometry )
00707 {
00708 d_data->sizeHintCache = QSize();
00709 updateGeometry();
00710 update();
00711 }
00712 }
00713
00715 void QwtSlider::valueChange()
00716 {
00717 QwtAbstractSlider::valueChange();
00718 update();
00719 }
00720
00721
00723 void QwtSlider::rangeChange()
00724 {
00725 d_data->map.setScaleInterval(minValue(), maxValue());
00726
00727 if (autoScale())
00728 rescale(minValue(), maxValue());
00729
00730 QwtAbstractSlider::rangeChange();
00731 layoutSlider();
00732 }
00733
00739 void QwtSlider::setMargins(int xMargin, int yMargin)
00740 {
00741 if ( xMargin < 0 )
00742 xMargin = 0;
00743 if ( yMargin < 0 )
00744 yMargin = 0;
00745
00746 if ( xMargin != d_data->xMargin || yMargin != d_data->yMargin )
00747 {
00748 d_data->xMargin = xMargin;
00749 d_data->yMargin = yMargin;
00750 layoutSlider();
00751 }
00752 }
00753
00757 void QwtSlider::setBgStyle(BGSTYLE st)
00758 {
00759 d_data->bgStyle = st;
00760 layoutSlider();
00761 }
00762
00766 QwtSlider::BGSTYLE QwtSlider::bgStyle() const
00767 {
00768 return d_data->bgStyle;
00769 }
00770
00774 int QwtSlider::thumbLength() const
00775 {
00776 return d_data->thumbLength;
00777 }
00778
00782 int QwtSlider::thumbWidth() const
00783 {
00784 return d_data->thumbWidth;
00785 }
00786
00790 int QwtSlider::borderWidth() const
00791 {
00792 return d_data->borderWidth;
00793 }
00794
00798 QSize QwtSlider::sizeHint() const
00799 {
00800 return minimumSizeHint();
00801 }
00802
00808 QSize QwtSlider::minimumSizeHint() const
00809 {
00810 if (!d_data->sizeHintCache.isEmpty())
00811 return d_data->sizeHintCache;
00812
00813 int sliderWidth = d_data->thumbWidth;
00814 if (d_data->bgStyle & BgTrough)
00815 sliderWidth += 2 * d_data->borderWidth;
00816
00817 int w = 0, h = 0;
00818 if (d_data->scalePos != NoScale)
00819 {
00820 int d1, d2;
00821 scaleDraw()->getBorderDistHint(font(), d1, d2);
00822 int msMbd = qwtMax(d1, d2);
00823
00824 int mbd = d_data->thumbLength / 2;
00825 if (d_data->bgStyle & BgTrough)
00826 mbd += d_data->borderWidth;
00827
00828 if ( mbd < msMbd )
00829 mbd = msMbd;
00830
00831 const int sdExtent = scaleDraw()->extent( QPen(), font() );
00832 const int sdLength = scaleDraw()->minLength( QPen(), font() );
00833
00834 h = sliderWidth + sdExtent + d_data->scaleDist;
00835 w = sdLength - 2 * msMbd + 2 * mbd;
00836 }
00837 else
00838 {
00839 w = 200;
00840 h = sliderWidth;
00841 }
00842
00843 if ( orientation() == Qt::Vertical )
00844 qSwap(w, h);
00845
00846 w += 2 * d_data->xMargin;
00847 h += 2 * d_data->yMargin;
00848
00849 d_data->sizeHintCache = QSize(w, h);
00850 return d_data->sizeHintCache;
00851 }