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
00065 QwtSlider::QwtSlider(QWidget *parent,
00066 Qt::Orientation orientation, ScalePos scalePos, BGSTYLE bgStyle):
00067 QwtAbstractSlider(orientation, parent)
00068 {
00069 if (orientation == Qt::Vertical)
00070 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
00071 else
00072 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
00073
00074 #if QT_VERSION >= 0x040000
00075 setAttribute(Qt::WA_WState_OwnSizePolicy, false);
00076 #else
00077 clearWState( WState_OwnSizePolicy );
00078 #endif
00079
00080
00081 #if QT_VERSION < 0x040000
00082 setWFlags(Qt::WNoAutoErase);
00083 #endif
00084
00085 d_data = new QwtSlider::PrivateData;
00086
00087 d_data->borderWidth = 2;
00088 d_data->scaleDist = 4;
00089 d_data->scalePos = scalePos;
00090 d_data->xMargin = 0;
00091 d_data->yMargin = 0;
00092 d_data->bgStyle = bgStyle;
00093
00094 if (bgStyle == BgSlot)
00095 {
00096 d_data->thumbLength = 16;
00097 d_data->thumbWidth = 30;
00098 }
00099 else
00100 {
00101 d_data->thumbLength = 31;
00102 d_data->thumbWidth = 16;
00103 }
00104
00105 d_data->sliderRect.setRect(0,0,8,8);
00106
00107 QwtScaleDraw::Alignment align;
00108 if ( orientation == Qt::Vertical )
00109 {
00110
00111 if ((d_data->scalePos == Bottom) || (d_data->scalePos == Top))
00112 d_data->scalePos = None;
00113
00114 if (d_data->scalePos == Right)
00115 align = QwtScaleDraw::RightScale;
00116 else
00117 align = QwtScaleDraw::LeftScale;
00118 }
00119 else
00120 {
00121
00122 if ((d_data->scalePos == Left) || (d_data->scalePos == Right))
00123 d_data->scalePos = None;
00124
00125 if (d_data->scalePos == Top)
00126 align = QwtScaleDraw::TopScale;
00127 else
00128 align = QwtScaleDraw::BottomScale;
00129 }
00130
00131 scaleDraw()->setAlignment(align);
00132 scaleDraw()->setLength(100);
00133
00134 setRange(0.0, 100.0, 1.0);
00135 setValue(0.0);
00136 }
00137
00138 QwtSlider::~QwtSlider()
00139 {
00140 delete d_data;
00141 }
00142
00151 void QwtSlider::setOrientation(Qt::Orientation o)
00152 {
00153 if ( o == orientation() )
00154 return;
00155
00156 if (o == Qt::Horizontal)
00157 {
00158 if ((d_data->scalePos == Left) || (d_data->scalePos == Right))
00159 d_data->scalePos = None;
00160 }
00161 else
00162 {
00163 if ((d_data->scalePos == Bottom) || (d_data->scalePos == Top))
00164 d_data->scalePos = None;
00165 }
00166
00167 #if QT_VERSION >= 0x040000
00168 if ( !testAttribute(Qt::WA_WState_OwnSizePolicy) )
00169 #else
00170 if ( !testWState( WState_OwnSizePolicy ) )
00171 #endif
00172 {
00173 QSizePolicy sp = sizePolicy();
00174 sp.transpose();
00175 setSizePolicy(sp);
00176
00177 #if QT_VERSION >= 0x040000
00178 setAttribute(Qt::WA_WState_OwnSizePolicy, false);
00179 #else
00180 clearWState( WState_OwnSizePolicy );
00181 #endif
00182 }
00183
00184 QwtAbstractSlider::setOrientation(o);
00185 layoutSlider();
00186 }
00187
00200 void QwtSlider::setScalePosition(ScalePos s)
00201 {
00202 d_data->scalePos = s;
00203 if ((s == Bottom) || (s == Top))
00204 setOrientation(Qt::Horizontal);
00205 else if ((s == Left) || (s == Right))
00206 setOrientation(Qt::Vertical);
00207 else
00208 layoutSlider();
00209 }
00210
00212 QwtSlider::ScalePos QwtSlider::scalePosition() const
00213 {
00214 return d_data->scalePos;
00215 }
00216
00221 void QwtSlider::setBorderWidth(int bd)
00222 {
00223 if ( bd < 0 )
00224 bd = 0;
00225
00226 if ( bd != d_data->borderWidth )
00227 {
00228 d_data->borderWidth = bd;
00229 layoutSlider();
00230 }
00231 }
00232
00237 void QwtSlider::setThumbLength(int thumbLength)
00238 {
00239 if ( thumbLength < 8 )
00240 thumbLength = 8;
00241
00242 if ( thumbLength != d_data->thumbLength )
00243 {
00244 d_data->thumbLength = thumbLength;
00245 layoutSlider();
00246 }
00247 }
00248
00253 void QwtSlider::setThumbWidth(int w)
00254 {
00255 if ( w < 4 )
00256 w = 4;
00257
00258 if ( d_data->thumbWidth != w )
00259 {
00260 d_data->thumbWidth = w;
00261 layoutSlider();
00262 }
00263 }
00264
00265 void QwtSlider::setScaleDraw(QwtScaleDraw *scaleDraw)
00266 {
00267 setAbstractScaleDraw(scaleDraw);
00268 }
00269
00270 const QwtScaleDraw *QwtSlider::scaleDraw() const
00271 {
00272 return (QwtScaleDraw *)abstractScaleDraw();
00273 }
00274
00275 QwtScaleDraw *QwtSlider::scaleDraw()
00276 {
00277 return (QwtScaleDraw *)abstractScaleDraw();
00278 }
00279
00281 void QwtSlider::scaleChange()
00282 {
00283 layoutSlider();
00284 }
00285
00286
00288 void QwtSlider::fontChange(const QFont &f)
00289 {
00290 QwtAbstractSlider::fontChange( f );
00291 layoutSlider();
00292 }
00293
00295 void QwtSlider::drawSlider(QPainter *p, const QRect &r)
00296 {
00297 QRect cr(r);
00298
00299 if (d_data->bgStyle & BgTrough)
00300 {
00301 qDrawShadePanel(p, r.x(), r.y(),
00302 r.width(), r.height(),
00303 #if QT_VERSION < 0x040000
00304 colorGroup(),
00305 #else
00306 palette(),
00307 #endif
00308 true, d_data->borderWidth,0);
00309
00310 cr.setRect(r.x() + d_data->borderWidth,
00311 r.y() + d_data->borderWidth,
00312 r.width() - 2 * d_data->borderWidth,
00313 r.height() - 2 * d_data->borderWidth);
00314
00315 p->fillRect(cr.x(), cr.y(), cr.width(), cr.height(),
00316 #if QT_VERSION < 0x040000
00317 colorGroup().brush(QColorGroup::Mid)
00318 #else
00319 palette().brush(QPalette::Mid)
00320 #endif
00321 );
00322 }
00323
00324 if ( d_data->bgStyle & BgSlot)
00325 {
00326 int ws = 4;
00327 int ds = d_data->thumbLength / 2 - 4;
00328 if ( ds < 1 )
00329 ds = 1;
00330
00331 QRect rSlot;
00332 if (orientation() == Qt::Horizontal)
00333 {
00334 if ( cr.height() & 1 )
00335 ws++;
00336 rSlot = QRect(cr.x() + ds,
00337 cr.y() + (cr.height() - ws) / 2,
00338 cr.width() - 2 * ds, ws);
00339 }
00340 else
00341 {
00342 if ( cr.width() & 1 )
00343 ws++;
00344 rSlot = QRect(cr.x() + (cr.width() - ws) / 2,
00345 cr.y() + ds,
00346 ws, cr.height() - 2 * ds);
00347 }
00348 p->fillRect(rSlot.x(), rSlot.y(), rSlot.width(), rSlot.height(),
00349 #if QT_VERSION < 0x040000
00350 colorGroup().brush(QColorGroup::Dark)
00351 #else
00352 palette().brush(QPalette::Dark)
00353 #endif
00354 );
00355 qDrawShadePanel(p, rSlot.x(), rSlot.y(),
00356 rSlot.width(), rSlot.height(),
00357 #if QT_VERSION < 0x040000
00358 colorGroup(),
00359 #else
00360 palette(),
00361 #endif
00362 true, 1 ,0);
00363
00364 }
00365
00366 if ( isValid() )
00367 drawThumb(p, cr, xyPosition(value()));
00368 }
00369
00371 void QwtSlider::drawThumb(QPainter *p, const QRect &sliderRect, int pos)
00372 {
00373 pos++;
00374 if (orientation() == Qt::Horizontal)
00375 {
00376 qDrawShadePanel(p, pos - d_data->thumbLength / 2,
00377 sliderRect.y(), d_data->thumbLength, sliderRect.height(),
00378 #if QT_VERSION < 0x040000
00379 colorGroup(),
00380 #else
00381 palette(),
00382 #endif
00383 false, d_data->borderWidth,
00384 #if QT_VERSION < 0x040000
00385 &colorGroup().brush(QColorGroup::Button)
00386 #else
00387 &palette().brush(QPalette::Button)
00388 #endif
00389 );
00390
00391 qDrawShadeLine(p, pos, sliderRect.y(),
00392 pos, sliderRect.y() + sliderRect.height() - 2,
00393 #if QT_VERSION < 0x040000
00394 colorGroup(),
00395 #else
00396 palette(),
00397 #endif
00398 true, 1);
00399 }
00400 else
00401 {
00402 qDrawShadePanel(p,sliderRect.x(), pos - d_data->thumbLength / 2,
00403 sliderRect.width(), d_data->thumbLength,
00404 #if QT_VERSION < 0x040000
00405 colorGroup(),
00406 #else
00407 palette(),
00408 #endif
00409 false, d_data->borderWidth,
00410 #if QT_VERSION < 0x040000
00411 &colorGroup().brush(QColorGroup::Button)
00412 #else
00413 &palette().brush(QPalette::Button)
00414 #endif
00415 );
00416
00417 qDrawShadeLine(p, sliderRect.x(), pos,
00418 sliderRect.x() + sliderRect.width() - 2, pos,
00419 #if QT_VERSION < 0x040000
00420 colorGroup(),
00421 #else
00422 palette(),
00423 #endif
00424 true, 1);
00425 }
00426 }
00427
00429 int QwtSlider::xyPosition(double v) const
00430 {
00431 return d_data->map.transform(v);
00432 }
00433
00435 double QwtSlider::getValue(const QPoint &p)
00436 {
00437 return d_data->map.invTransform(
00438 orientation() == Qt::Horizontal ? p.x() : p.y());
00439 }
00440
00441
00448 void QwtSlider::getScrollMode(const QPoint &p,
00449 int &scrollMode, int &direction )
00450 {
00451 if (!d_data->sliderRect.contains(p))
00452 {
00453 scrollMode = ScrNone;
00454 direction = 0;
00455 return;
00456 }
00457
00458 const int pos = ( orientation() == Qt::Horizontal ) ? p.x() : p.y();
00459 const int markerPos = xyPosition(value());
00460
00461 if ((pos > markerPos - d_data->thumbLength / 2)
00462 && (pos < markerPos + d_data->thumbLength / 2))
00463 {
00464 scrollMode = ScrMouse;
00465 direction = 0;
00466 return;
00467 }
00468
00469 scrollMode = ScrPage;
00470 direction = (pos > markerPos) ? 1 : -1;
00471
00472 if ( scaleDraw()->map().p1() > scaleDraw()->map().p2() )
00473 direction = -direction;
00474 }
00475
00477 void QwtSlider::paintEvent(QPaintEvent *e)
00478 {
00479 const QRect &ur = e->rect();
00480 if ( ur.isValid() )
00481 {
00482 #if QT_VERSION < 0x040000
00483 QwtPaintBuffer paintBuffer(this, ur);
00484 draw(paintBuffer.painter(), ur);
00485 #else
00486 QPainter painter(this);
00487 draw(&painter, ur);
00488 #endif
00489 }
00490 }
00491
00493 void QwtSlider::draw(QPainter *painter, const QRect&)
00494 {
00495 if (d_data->scalePos != None)
00496 {
00497 #if QT_VERSION < 0x040000
00498 scaleDraw()->draw(painter, colorGroup());
00499 #else
00500 scaleDraw()->draw(painter, palette());
00501 #endif
00502 }
00503
00504 drawSlider(painter, d_data->sliderRect);
00505
00506 if ( hasFocus() )
00507 QwtPainter::drawFocusRect(painter, this, d_data->sliderRect);
00508 }
00509
00511 void QwtSlider::resizeEvent(QResizeEvent *)
00512 {
00513 layoutSlider( false );
00514 }
00515
00522 void QwtSlider::layoutSlider( bool update_geometry )
00523 {
00524 int sliderWidth = d_data->thumbWidth;
00525 int sld1 = d_data->thumbLength / 2 - 1;
00526 int sld2 = d_data->thumbLength / 2 + d_data->thumbLength % 2;
00527 if ( d_data->bgStyle & BgTrough )
00528 {
00529 sliderWidth += 2 * d_data->borderWidth;
00530 sld1 += d_data->borderWidth;
00531 sld2 += d_data->borderWidth;
00532 }
00533
00534 int scd = 0;
00535 if ( d_data->scalePos != None )
00536 {
00537 int d1, d2;
00538 scaleDraw()->getBorderDistHint(font(), d1, d2);
00539 scd = qwtMax(d1, d2);
00540 }
00541
00542 int slo = scd - sld1;
00543 if ( slo < 0 )
00544 slo = 0;
00545
00546 int x, y, length;
00547
00548 const QRect r = rect();
00549 if (orientation() == Qt::Horizontal)
00550 {
00551 switch (d_data->scalePos)
00552 {
00553 case Top:
00554 {
00555 d_data->sliderRect.setRect(
00556 r.x() + d_data->xMargin + slo,
00557 r.y() + r.height() -
00558 d_data->yMargin - sliderWidth,
00559 r.width() - 2 * d_data->xMargin - 2 * slo,
00560 sliderWidth);
00561
00562 x = d_data->sliderRect.x() + sld1;
00563 y = d_data->sliderRect.y() - d_data->scaleDist;
00564
00565 break;
00566 }
00567
00568 case Bottom:
00569 {
00570 d_data->sliderRect.setRect(
00571 r.x() + d_data->xMargin + slo,
00572 r.y() + d_data->yMargin,
00573 r.width() - 2 * d_data->xMargin - 2 * slo,
00574 sliderWidth);
00575
00576 x = d_data->sliderRect.x() + sld1;
00577 y = d_data->sliderRect.y() + d_data->sliderRect.height()
00578 + d_data->scaleDist;
00579
00580 break;
00581 }
00582
00583 case None:
00584 default:
00585 {
00586 d_data->sliderRect.setRect(
00587 r.x() + d_data->xMargin + slo,
00588 r.y() + d_data->yMargin,
00589 r.width() - 2 * d_data->xMargin - 2 * slo,
00590 sliderWidth);
00591
00592 x = d_data->sliderRect.x() + sld1;
00593 y = 0;
00594
00595 break;
00596 }
00597 }
00598 length = d_data->sliderRect.width() - (sld1 + sld2);
00599 }
00600 else
00601 {
00602 switch (d_data->scalePos)
00603 {
00604 case Right:
00605 d_data->sliderRect.setRect(
00606 r.x() + d_data->xMargin,
00607 r.y() + d_data->yMargin + slo,
00608 sliderWidth,
00609 r.height() - 2 * d_data->yMargin - 2 * slo);
00610
00611 x = d_data->sliderRect.x() + d_data->sliderRect.width()
00612 + d_data->scaleDist;
00613 y = d_data->sliderRect.y() + sld1;
00614
00615 break;
00616
00617 case Left:
00618 d_data->sliderRect.setRect(
00619 r.x() + r.width() - sliderWidth - d_data->xMargin,
00620 r.y() + d_data->yMargin + slo,
00621 sliderWidth,
00622 r.height() - 2 * d_data->yMargin - 2 * slo);
00623
00624 x = d_data->sliderRect.x() - d_data->scaleDist;
00625 y = d_data->sliderRect.y() + sld1;
00626
00627 break;
00628
00629 case None:
00630 default:
00631 d_data->sliderRect.setRect(
00632 r.x() + r.width() - sliderWidth - d_data->xMargin,
00633 r.y() + d_data->yMargin + slo,
00634 sliderWidth,
00635 r.height() - 2 * d_data->yMargin - 2 * slo);
00636
00637 x = 0;
00638 y = d_data->sliderRect.y() + sld1;
00639
00640 break;
00641 }
00642 length = d_data->sliderRect.height() - (sld1 + sld2);
00643 }
00644
00645 scaleDraw()->move(x, y);
00646 scaleDraw()->setLength(length);
00647
00648 d_data->map.setPaintXInterval(scaleDraw()->map().p1(),
00649 scaleDraw()->map().p2());
00650
00651 if ( update_geometry )
00652 {
00653 d_data->sizeHintCache = QSize();
00654 updateGeometry();
00655 update();
00656 }
00657 }
00658
00660 void QwtSlider::valueChange()
00661 {
00662 QwtAbstractSlider::valueChange();
00663 update();
00664 }
00665
00666
00668 void QwtSlider::rangeChange()
00669 {
00670 d_data->map.setScaleInterval(minValue(), maxValue());
00671
00672 if (autoScale())
00673 rescale(minValue(), maxValue());
00674
00675 QwtAbstractSlider::rangeChange();
00676 layoutSlider();
00677 }
00678
00684 void QwtSlider::setMargins(int xMargin, int yMargin)
00685 {
00686 if ( xMargin < 0 )
00687 xMargin = 0;
00688 if ( yMargin < 0 )
00689 yMargin = 0;
00690
00691 if ( xMargin != d_data->xMargin || yMargin != d_data->yMargin )
00692 {
00693 d_data->xMargin = xMargin;
00694 d_data->yMargin = yMargin;
00695 layoutSlider();
00696 }
00697 }
00698
00702 void QwtSlider::setBgStyle(BGSTYLE st)
00703 {
00704 d_data->bgStyle = st;
00705 layoutSlider();
00706 }
00707
00711 QwtSlider::BGSTYLE QwtSlider::bgStyle() const
00712 {
00713 return d_data->bgStyle;
00714 }
00715
00719 int QwtSlider::thumbLength() const
00720 {
00721 return d_data->thumbLength;
00722 }
00723
00727 int QwtSlider::thumbWidth() const
00728 {
00729 return d_data->thumbWidth;
00730 }
00731
00735 int QwtSlider::borderWidth() const
00736 {
00737 return d_data->borderWidth;
00738 }
00739
00743 QSize QwtSlider::sizeHint() const
00744 {
00745 return minimumSizeHint();
00746 }
00747
00753 QSize QwtSlider::minimumSizeHint() const
00754 {
00755 if (!d_data->sizeHintCache.isEmpty())
00756 return d_data->sizeHintCache;
00757
00758 int sliderWidth = d_data->thumbWidth;
00759 if (d_data->bgStyle & BgTrough)
00760 sliderWidth += 2 * d_data->borderWidth;
00761
00762 int w = 0, h = 0;
00763 if (d_data->scalePos != None)
00764 {
00765 int d1, d2;
00766 scaleDraw()->getBorderDistHint(font(), d1, d2);
00767 int msMbd = qwtMax(d1, d2);
00768
00769 int mbd = d_data->thumbLength / 2;
00770 if (d_data->bgStyle & BgTrough)
00771 mbd += d_data->borderWidth;
00772
00773 if ( mbd < msMbd )
00774 mbd = msMbd;
00775
00776 const int sdExtent = scaleDraw()->extent( QPen(), font() );
00777 const int sdLength = scaleDraw()->minLength( QPen(), font() );
00778
00779 h = sliderWidth + sdExtent + d_data->scaleDist;
00780 w = sdLength - 2 * msMbd + 2 * mbd;
00781 }
00782 else
00783 {
00784 w = 200;
00785 h = sliderWidth;
00786 }
00787
00788 if ( orientation() == Qt::Vertical )
00789 qSwap(w, h);
00790
00791 w += 2 * d_data->xMargin;
00792 h += 2 * d_data->yMargin;
00793
00794 d_data->sizeHintCache = QSize(w, h);
00795 return d_data->sizeHintCache;
00796 }