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 d_data->scalePos = s;
00227 if ((s == BottomScale) || (s == TopScale))
00228 setOrientation(Qt::Horizontal);
00229 else if ((s == LeftScale) || (s == RightScale))
00230 setOrientation(Qt::Vertical);
00231 else
00232 layoutSlider();
00233 }
00234
00236 QwtSlider::ScalePos QwtSlider::scalePosition() const
00237 {
00238 return d_data->scalePos;
00239 }
00240
00245 void QwtSlider::setBorderWidth(int bd)
00246 {
00247 if ( bd < 0 )
00248 bd = 0;
00249
00250 if ( bd != d_data->borderWidth )
00251 {
00252 d_data->borderWidth = bd;
00253 layoutSlider();
00254 }
00255 }
00256
00261 void QwtSlider::setThumbLength(int thumbLength)
00262 {
00263 if ( thumbLength < 8 )
00264 thumbLength = 8;
00265
00266 if ( thumbLength != d_data->thumbLength )
00267 {
00268 d_data->thumbLength = thumbLength;
00269 layoutSlider();
00270 }
00271 }
00272
00277 void QwtSlider::setThumbWidth(int w)
00278 {
00279 if ( w < 4 )
00280 w = 4;
00281
00282 if ( d_data->thumbWidth != w )
00283 {
00284 d_data->thumbWidth = w;
00285 layoutSlider();
00286 }
00287 }
00288
00289 void QwtSlider::setScaleDraw(QwtScaleDraw *scaleDraw)
00290 {
00291 setAbstractScaleDraw(scaleDraw);
00292 }
00293
00294 const QwtScaleDraw *QwtSlider::scaleDraw() const
00295 {
00296 return (QwtScaleDraw *)abstractScaleDraw();
00297 }
00298
00299 QwtScaleDraw *QwtSlider::scaleDraw()
00300 {
00301 return (QwtScaleDraw *)abstractScaleDraw();
00302 }
00303
00305 void QwtSlider::scaleChange()
00306 {
00307 layoutSlider();
00308 }
00309
00310
00312 void QwtSlider::fontChange(const QFont &f)
00313 {
00314 QwtAbstractSlider::fontChange( f );
00315 layoutSlider();
00316 }
00317
00319 void QwtSlider::drawSlider(QPainter *p, const QRect &r)
00320 {
00321 QRect cr(r);
00322
00323 if (d_data->bgStyle & BgTrough)
00324 {
00325 qDrawShadePanel(p, r.x(), r.y(),
00326 r.width(), r.height(),
00327 #if QT_VERSION < 0x040000
00328 colorGroup(),
00329 #else
00330 palette(),
00331 #endif
00332 true, d_data->borderWidth,0);
00333
00334 cr.setRect(r.x() + d_data->borderWidth,
00335 r.y() + d_data->borderWidth,
00336 r.width() - 2 * d_data->borderWidth,
00337 r.height() - 2 * d_data->borderWidth);
00338
00339 p->fillRect(cr.x(), cr.y(), cr.width(), cr.height(),
00340 #if QT_VERSION < 0x040000
00341 colorGroup().brush(QColorGroup::Mid)
00342 #else
00343 palette().brush(QPalette::Mid)
00344 #endif
00345 );
00346 }
00347
00348 if ( d_data->bgStyle & BgSlot)
00349 {
00350 int ws = 4;
00351 int ds = d_data->thumbLength / 2 - 4;
00352 if ( ds < 1 )
00353 ds = 1;
00354
00355 QRect rSlot;
00356 if (orientation() == Qt::Horizontal)
00357 {
00358 if ( cr.height() & 1 )
00359 ws++;
00360 rSlot = QRect(cr.x() + ds,
00361 cr.y() + (cr.height() - ws) / 2,
00362 cr.width() - 2 * ds, ws);
00363 }
00364 else
00365 {
00366 if ( cr.width() & 1 )
00367 ws++;
00368 rSlot = QRect(cr.x() + (cr.width() - ws) / 2,
00369 cr.y() + ds,
00370 ws, cr.height() - 2 * ds);
00371 }
00372 p->fillRect(rSlot.x(), rSlot.y(), rSlot.width(), rSlot.height(),
00373 #if QT_VERSION < 0x040000
00374 colorGroup().brush(QColorGroup::Dark)
00375 #else
00376 palette().brush(QPalette::Dark)
00377 #endif
00378 );
00379 qDrawShadePanel(p, rSlot.x(), rSlot.y(),
00380 rSlot.width(), rSlot.height(),
00381 #if QT_VERSION < 0x040000
00382 colorGroup(),
00383 #else
00384 palette(),
00385 #endif
00386 true, 1 ,0);
00387
00388 }
00389
00390 if ( isValid() )
00391 drawThumb(p, cr, xyPosition(value()));
00392 }
00393
00395 void QwtSlider::drawThumb(QPainter *p, const QRect &sliderRect, int pos)
00396 {
00397 pos++;
00398 if (orientation() == Qt::Horizontal)
00399 {
00400 qDrawShadePanel(p, pos - d_data->thumbLength / 2,
00401 sliderRect.y(), d_data->thumbLength, sliderRect.height(),
00402 #if QT_VERSION < 0x040000
00403 colorGroup(),
00404 #else
00405 palette(),
00406 #endif
00407 false, d_data->borderWidth,
00408 #if QT_VERSION < 0x040000
00409 &colorGroup().brush(QColorGroup::Button)
00410 #else
00411 &palette().brush(QPalette::Button)
00412 #endif
00413 );
00414
00415 qDrawShadeLine(p, pos, sliderRect.y(),
00416 pos, sliderRect.y() + sliderRect.height() - 2,
00417 #if QT_VERSION < 0x040000
00418 colorGroup(),
00419 #else
00420 palette(),
00421 #endif
00422 true, 1);
00423 }
00424 else
00425 {
00426 qDrawShadePanel(p,sliderRect.x(), pos - d_data->thumbLength / 2,
00427 sliderRect.width(), d_data->thumbLength,
00428 #if QT_VERSION < 0x040000
00429 colorGroup(),
00430 #else
00431 palette(),
00432 #endif
00433 false, d_data->borderWidth,
00434 #if QT_VERSION < 0x040000
00435 &colorGroup().brush(QColorGroup::Button)
00436 #else
00437 &palette().brush(QPalette::Button)
00438 #endif
00439 );
00440
00441 qDrawShadeLine(p, sliderRect.x(), pos,
00442 sliderRect.x() + sliderRect.width() - 2, pos,
00443 #if QT_VERSION < 0x040000
00444 colorGroup(),
00445 #else
00446 palette(),
00447 #endif
00448 true, 1);
00449 }
00450 }
00451
00453 int QwtSlider::xyPosition(double v) const
00454 {
00455 return d_data->map.transform(v);
00456 }
00457
00459 double QwtSlider::getValue(const QPoint &p)
00460 {
00461 return d_data->map.invTransform(
00462 orientation() == Qt::Horizontal ? p.x() : p.y());
00463 }
00464
00465
00472 void QwtSlider::getScrollMode(const QPoint &p,
00473 int &scrollMode, int &direction )
00474 {
00475 if (!d_data->sliderRect.contains(p))
00476 {
00477 scrollMode = ScrNone;
00478 direction = 0;
00479 return;
00480 }
00481
00482 const int pos = ( orientation() == Qt::Horizontal ) ? p.x() : p.y();
00483 const int markerPos = xyPosition(value());
00484
00485 if ((pos > markerPos - d_data->thumbLength / 2)
00486 && (pos < markerPos + d_data->thumbLength / 2))
00487 {
00488 scrollMode = ScrMouse;
00489 direction = 0;
00490 return;
00491 }
00492
00493 scrollMode = ScrPage;
00494 direction = (pos > markerPos) ? 1 : -1;
00495
00496 if ( scaleDraw()->map().p1() > scaleDraw()->map().p2() )
00497 direction = -direction;
00498 }
00499
00501 void QwtSlider::paintEvent(QPaintEvent *e)
00502 {
00503 const QRect &ur = e->rect();
00504 if ( ur.isValid() )
00505 {
00506 #if QT_VERSION < 0x040000
00507 QwtPaintBuffer paintBuffer(this, ur);
00508 draw(paintBuffer.painter(), ur);
00509 #else
00510 QPainter painter(this);
00511 draw(&painter, ur);
00512 #endif
00513 }
00514 }
00515
00517 void QwtSlider::draw(QPainter *painter, const QRect&)
00518 {
00519 if (d_data->scalePos != NoScale)
00520 {
00521 #if QT_VERSION < 0x040000
00522 scaleDraw()->draw(painter, colorGroup());
00523 #else
00524 scaleDraw()->draw(painter, palette());
00525 #endif
00526 }
00527
00528 drawSlider(painter, d_data->sliderRect);
00529
00530 if ( hasFocus() )
00531 QwtPainter::drawFocusRect(painter, this, d_data->sliderRect);
00532 }
00533
00535 void QwtSlider::resizeEvent(QResizeEvent *)
00536 {
00537 layoutSlider( false );
00538 }
00539
00546 void QwtSlider::layoutSlider( bool update_geometry )
00547 {
00548 int sliderWidth = d_data->thumbWidth;
00549 int sld1 = d_data->thumbLength / 2 - 1;
00550 int sld2 = d_data->thumbLength / 2 + d_data->thumbLength % 2;
00551 if ( d_data->bgStyle & BgTrough )
00552 {
00553 sliderWidth += 2 * d_data->borderWidth;
00554 sld1 += d_data->borderWidth;
00555 sld2 += d_data->borderWidth;
00556 }
00557
00558 int scd = 0;
00559 if ( d_data->scalePos != NoScale )
00560 {
00561 int d1, d2;
00562 scaleDraw()->getBorderDistHint(font(), d1, d2);
00563 scd = qwtMax(d1, d2);
00564 }
00565
00566 int slo = scd - sld1;
00567 if ( slo < 0 )
00568 slo = 0;
00569
00570 int x, y, length;
00571
00572 const QRect r = rect();
00573 if (orientation() == Qt::Horizontal)
00574 {
00575 switch (d_data->scalePos)
00576 {
00577 case TopScale:
00578 {
00579 d_data->sliderRect.setRect(
00580 r.x() + d_data->xMargin + slo,
00581 r.y() + r.height() -
00582 d_data->yMargin - sliderWidth,
00583 r.width() - 2 * d_data->xMargin - 2 * slo,
00584 sliderWidth);
00585
00586 x = d_data->sliderRect.x() + sld1;
00587 y = d_data->sliderRect.y() - d_data->scaleDist;
00588
00589 break;
00590 }
00591
00592 case BottomScale:
00593 {
00594 d_data->sliderRect.setRect(
00595 r.x() + d_data->xMargin + slo,
00596 r.y() + d_data->yMargin,
00597 r.width() - 2 * d_data->xMargin - 2 * slo,
00598 sliderWidth);
00599
00600 x = d_data->sliderRect.x() + sld1;
00601 y = d_data->sliderRect.y() + d_data->sliderRect.height()
00602 + d_data->scaleDist;
00603
00604 break;
00605 }
00606
00607 case NoScale:
00608 default:
00609 {
00610 d_data->sliderRect.setRect(
00611 r.x() + d_data->xMargin + slo,
00612 r.y() + d_data->yMargin,
00613 r.width() - 2 * d_data->xMargin - 2 * slo,
00614 sliderWidth);
00615
00616 x = d_data->sliderRect.x() + sld1;
00617 y = 0;
00618
00619 break;
00620 }
00621 }
00622 length = d_data->sliderRect.width() - (sld1 + sld2);
00623 }
00624 else
00625 {
00626 switch (d_data->scalePos)
00627 {
00628 case RightScale:
00629 d_data->sliderRect.setRect(
00630 r.x() + d_data->xMargin,
00631 r.y() + d_data->yMargin + slo,
00632 sliderWidth,
00633 r.height() - 2 * d_data->yMargin - 2 * slo);
00634
00635 x = d_data->sliderRect.x() + d_data->sliderRect.width()
00636 + d_data->scaleDist;
00637 y = d_data->sliderRect.y() + sld1;
00638
00639 break;
00640
00641 case LeftScale:
00642 d_data->sliderRect.setRect(
00643 r.x() + r.width() - sliderWidth - d_data->xMargin,
00644 r.y() + d_data->yMargin + slo,
00645 sliderWidth,
00646 r.height() - 2 * d_data->yMargin - 2 * slo);
00647
00648 x = d_data->sliderRect.x() - d_data->scaleDist;
00649 y = d_data->sliderRect.y() + sld1;
00650
00651 break;
00652
00653 case NoScale:
00654 default:
00655 d_data->sliderRect.setRect(
00656 r.x() + r.width() - sliderWidth - d_data->xMargin,
00657 r.y() + d_data->yMargin + slo,
00658 sliderWidth,
00659 r.height() - 2 * d_data->yMargin - 2 * slo);
00660
00661 x = 0;
00662 y = d_data->sliderRect.y() + sld1;
00663
00664 break;
00665 }
00666 length = d_data->sliderRect.height() - (sld1 + sld2);
00667 }
00668
00669 scaleDraw()->move(x, y);
00670 scaleDraw()->setLength(length);
00671
00672 d_data->map.setPaintXInterval(scaleDraw()->map().p1(),
00673 scaleDraw()->map().p2());
00674
00675 if ( update_geometry )
00676 {
00677 d_data->sizeHintCache = QSize();
00678 updateGeometry();
00679 update();
00680 }
00681 }
00682
00684 void QwtSlider::valueChange()
00685 {
00686 QwtAbstractSlider::valueChange();
00687 update();
00688 }
00689
00690
00692 void QwtSlider::rangeChange()
00693 {
00694 d_data->map.setScaleInterval(minValue(), maxValue());
00695
00696 if (autoScale())
00697 rescale(minValue(), maxValue());
00698
00699 QwtAbstractSlider::rangeChange();
00700 layoutSlider();
00701 }
00702
00708 void QwtSlider::setMargins(int xMargin, int yMargin)
00709 {
00710 if ( xMargin < 0 )
00711 xMargin = 0;
00712 if ( yMargin < 0 )
00713 yMargin = 0;
00714
00715 if ( xMargin != d_data->xMargin || yMargin != d_data->yMargin )
00716 {
00717 d_data->xMargin = xMargin;
00718 d_data->yMargin = yMargin;
00719 layoutSlider();
00720 }
00721 }
00722
00726 void QwtSlider::setBgStyle(BGSTYLE st)
00727 {
00728 d_data->bgStyle = st;
00729 layoutSlider();
00730 }
00731
00735 QwtSlider::BGSTYLE QwtSlider::bgStyle() const
00736 {
00737 return d_data->bgStyle;
00738 }
00739
00743 int QwtSlider::thumbLength() const
00744 {
00745 return d_data->thumbLength;
00746 }
00747
00751 int QwtSlider::thumbWidth() const
00752 {
00753 return d_data->thumbWidth;
00754 }
00755
00759 int QwtSlider::borderWidth() const
00760 {
00761 return d_data->borderWidth;
00762 }
00763
00767 QSize QwtSlider::sizeHint() const
00768 {
00769 return minimumSizeHint();
00770 }
00771
00777 QSize QwtSlider::minimumSizeHint() const
00778 {
00779 if (!d_data->sizeHintCache.isEmpty())
00780 return d_data->sizeHintCache;
00781
00782 int sliderWidth = d_data->thumbWidth;
00783 if (d_data->bgStyle & BgTrough)
00784 sliderWidth += 2 * d_data->borderWidth;
00785
00786 int w = 0, h = 0;
00787 if (d_data->scalePos != NoScale)
00788 {
00789 int d1, d2;
00790 scaleDraw()->getBorderDistHint(font(), d1, d2);
00791 int msMbd = qwtMax(d1, d2);
00792
00793 int mbd = d_data->thumbLength / 2;
00794 if (d_data->bgStyle & BgTrough)
00795 mbd += d_data->borderWidth;
00796
00797 if ( mbd < msMbd )
00798 mbd = msMbd;
00799
00800 const int sdExtent = scaleDraw()->extent( QPen(), font() );
00801 const int sdLength = scaleDraw()->minLength( QPen(), font() );
00802
00803 h = sliderWidth + sdExtent + d_data->scaleDist;
00804 w = sdLength - 2 * msMbd + 2 * mbd;
00805 }
00806 else
00807 {
00808 w = 200;
00809 h = sliderWidth;
00810 }
00811
00812 if ( orientation() == Qt::Vertical )
00813 qSwap(w, h);
00814
00815 w += 2 * d_data->xMargin;
00816 h += 2 * d_data->yMargin;
00817
00818 d_data->sizeHintCache = QSize(w, h);
00819 return d_data->sizeHintCache;
00820 }