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
00377 void QwtSlider::drawSlider(QPainter *p, const QRect &r)
00378 {
00379 QRect cr(r);
00380
00381 if (d_data->bgStyle & BgTrough)
00382 {
00383 qDrawShadePanel(p, r.x(), r.y(),
00384 r.width(), r.height(),
00385 #if QT_VERSION < 0x040000
00386 colorGroup(),
00387 #else
00388 palette(),
00389 #endif
00390 true, d_data->borderWidth,0);
00391
00392 cr.setRect(r.x() + d_data->borderWidth,
00393 r.y() + d_data->borderWidth,
00394 r.width() - 2 * d_data->borderWidth,
00395 r.height() - 2 * d_data->borderWidth);
00396
00397 p->fillRect(cr.x(), cr.y(), cr.width(), cr.height(),
00398 #if QT_VERSION < 0x040000
00399 colorGroup().brush(QColorGroup::Mid)
00400 #else
00401 palette().brush(QPalette::Mid)
00402 #endif
00403 );
00404 }
00405
00406 if ( d_data->bgStyle & BgSlot)
00407 {
00408 int ws = 4;
00409 int ds = d_data->thumbLength / 2 - 4;
00410 if ( ds < 1 )
00411 ds = 1;
00412
00413 QRect rSlot;
00414 if (orientation() == Qt::Horizontal)
00415 {
00416 if ( cr.height() & 1 )
00417 ws++;
00418 rSlot = QRect(cr.x() + ds,
00419 cr.y() + (cr.height() - ws) / 2,
00420 cr.width() - 2 * ds, ws);
00421 }
00422 else
00423 {
00424 if ( cr.width() & 1 )
00425 ws++;
00426 rSlot = QRect(cr.x() + (cr.width() - ws) / 2,
00427 cr.y() + ds,
00428 ws, cr.height() - 2 * ds);
00429 }
00430 p->fillRect(rSlot.x(), rSlot.y(), rSlot.width(), rSlot.height(),
00431 #if QT_VERSION < 0x040000
00432 colorGroup().brush(QColorGroup::Dark)
00433 #else
00434 palette().brush(QPalette::Dark)
00435 #endif
00436 );
00437 qDrawShadePanel(p, rSlot.x(), rSlot.y(),
00438 rSlot.width(), rSlot.height(),
00439 #if QT_VERSION < 0x040000
00440 colorGroup(),
00441 #else
00442 palette(),
00443 #endif
00444 true, 1 ,0);
00445
00446 }
00447
00448 if ( isValid() )
00449 drawThumb(p, cr, xyPosition(value()));
00450 }
00451
00453 void QwtSlider::drawThumb(QPainter *p, const QRect &sliderRect, int pos)
00454 {
00455 pos++;
00456 if (orientation() == Qt::Horizontal)
00457 {
00458 qDrawShadePanel(p, pos - d_data->thumbLength / 2,
00459 sliderRect.y(), d_data->thumbLength, sliderRect.height(),
00460 #if QT_VERSION < 0x040000
00461 colorGroup(),
00462 #else
00463 palette(),
00464 #endif
00465 false, d_data->borderWidth,
00466 #if QT_VERSION < 0x040000
00467 &colorGroup().brush(QColorGroup::Button)
00468 #else
00469 &palette().brush(QPalette::Button)
00470 #endif
00471 );
00472
00473 qDrawShadeLine(p, pos, sliderRect.y(),
00474 pos, sliderRect.y() + sliderRect.height() - 2,
00475 #if QT_VERSION < 0x040000
00476 colorGroup(),
00477 #else
00478 palette(),
00479 #endif
00480 true, 1);
00481 }
00482 else
00483 {
00484 qDrawShadePanel(p,sliderRect.x(), pos - d_data->thumbLength / 2,
00485 sliderRect.width(), d_data->thumbLength,
00486 #if QT_VERSION < 0x040000
00487 colorGroup(),
00488 #else
00489 palette(),
00490 #endif
00491 false, d_data->borderWidth,
00492 #if QT_VERSION < 0x040000
00493 &colorGroup().brush(QColorGroup::Button)
00494 #else
00495 &palette().brush(QPalette::Button)
00496 #endif
00497 );
00498
00499 qDrawShadeLine(p, sliderRect.x(), pos,
00500 sliderRect.x() + sliderRect.width() - 2, pos,
00501 #if QT_VERSION < 0x040000
00502 colorGroup(),
00503 #else
00504 palette(),
00505 #endif
00506 true, 1);
00507 }
00508 }
00509
00511 int QwtSlider::xyPosition(double v) const
00512 {
00513 return d_data->map.transform(v);
00514 }
00515
00517 double QwtSlider::getValue(const QPoint &p)
00518 {
00519 return d_data->map.invTransform(
00520 orientation() == Qt::Horizontal ? p.x() : p.y());
00521 }
00522
00523
00530 void QwtSlider::getScrollMode(const QPoint &p,
00531 int &scrollMode, int &direction )
00532 {
00533 if (!d_data->sliderRect.contains(p))
00534 {
00535 scrollMode = ScrNone;
00536 direction = 0;
00537 return;
00538 }
00539
00540 const int pos = ( orientation() == Qt::Horizontal ) ? p.x() : p.y();
00541 const int markerPos = xyPosition(value());
00542
00543 if ((pos > markerPos - d_data->thumbLength / 2)
00544 && (pos < markerPos + d_data->thumbLength / 2))
00545 {
00546 scrollMode = ScrMouse;
00547 direction = 0;
00548 return;
00549 }
00550
00551 scrollMode = ScrPage;
00552 direction = (pos > markerPos) ? 1 : -1;
00553
00554 if ( scaleDraw()->map().p1() > scaleDraw()->map().p2() )
00555 direction = -direction;
00556 }
00557
00559 void QwtSlider::paintEvent(QPaintEvent *e)
00560 {
00561 const QRect &ur = e->rect();
00562 if ( ur.isValid() )
00563 {
00564 #if QT_VERSION < 0x040000
00565 QwtPaintBuffer paintBuffer(this, ur);
00566 draw(paintBuffer.painter(), ur);
00567 #else
00568 QPainter painter(this);
00569 draw(&painter, ur);
00570 #endif
00571 }
00572 }
00573
00575 void QwtSlider::draw(QPainter *painter, const QRect&)
00576 {
00577 if (d_data->scalePos != NoScale)
00578 {
00579 #if QT_VERSION < 0x040000
00580 scaleDraw()->draw(painter, colorGroup());
00581 #else
00582 scaleDraw()->draw(painter, palette());
00583 #endif
00584 }
00585
00586 drawSlider(painter, d_data->sliderRect);
00587
00588 if ( hasFocus() )
00589 QwtPainter::drawFocusRect(painter, this, d_data->sliderRect);
00590 }
00591
00593 void QwtSlider::resizeEvent(QResizeEvent *)
00594 {
00595 layoutSlider( false );
00596 }
00597
00604 void QwtSlider::layoutSlider( bool update_geometry )
00605 {
00606 int sliderWidth = d_data->thumbWidth;
00607 int sld1 = d_data->thumbLength / 2 - 1;
00608 int sld2 = d_data->thumbLength / 2 + d_data->thumbLength % 2;
00609 if ( d_data->bgStyle & BgTrough )
00610 {
00611 sliderWidth += 2 * d_data->borderWidth;
00612 sld1 += d_data->borderWidth;
00613 sld2 += d_data->borderWidth;
00614 }
00615
00616 int scd = 0;
00617 if ( d_data->scalePos != NoScale )
00618 {
00619 int d1, d2;
00620 scaleDraw()->getBorderDistHint(font(), d1, d2);
00621 scd = qwtMax(d1, d2);
00622 }
00623
00624 int slo = scd - sld1;
00625 if ( slo < 0 )
00626 slo = 0;
00627
00628 int x, y, length;
00629
00630 const QRect r = rect();
00631 if (orientation() == Qt::Horizontal)
00632 {
00633 switch (d_data->scalePos)
00634 {
00635 case TopScale:
00636 {
00637 d_data->sliderRect.setRect(
00638 r.x() + d_data->xMargin + slo,
00639 r.y() + r.height() -
00640 d_data->yMargin - sliderWidth,
00641 r.width() - 2 * d_data->xMargin - 2 * slo,
00642 sliderWidth);
00643
00644 x = d_data->sliderRect.x() + sld1;
00645 y = d_data->sliderRect.y() - d_data->scaleDist;
00646
00647 break;
00648 }
00649
00650 case BottomScale:
00651 {
00652 d_data->sliderRect.setRect(
00653 r.x() + d_data->xMargin + slo,
00654 r.y() + d_data->yMargin,
00655 r.width() - 2 * d_data->xMargin - 2 * slo,
00656 sliderWidth);
00657
00658 x = d_data->sliderRect.x() + sld1;
00659 y = d_data->sliderRect.y() + d_data->sliderRect.height()
00660 + d_data->scaleDist;
00661
00662 break;
00663 }
00664
00665 case NoScale:
00666 default:
00667 {
00668 d_data->sliderRect.setRect(
00669 r.x() + d_data->xMargin + slo,
00670 r.y() + d_data->yMargin,
00671 r.width() - 2 * d_data->xMargin - 2 * slo,
00672 sliderWidth);
00673
00674 x = d_data->sliderRect.x() + sld1;
00675 y = 0;
00676
00677 break;
00678 }
00679 }
00680 length = d_data->sliderRect.width() - (sld1 + sld2);
00681 }
00682 else
00683 {
00684 switch (d_data->scalePos)
00685 {
00686 case RightScale:
00687 d_data->sliderRect.setRect(
00688 r.x() + d_data->xMargin,
00689 r.y() + d_data->yMargin + slo,
00690 sliderWidth,
00691 r.height() - 2 * d_data->yMargin - 2 * slo);
00692
00693 x = d_data->sliderRect.x() + d_data->sliderRect.width()
00694 + d_data->scaleDist;
00695 y = d_data->sliderRect.y() + sld1;
00696
00697 break;
00698
00699 case LeftScale:
00700 d_data->sliderRect.setRect(
00701 r.x() + r.width() - sliderWidth - d_data->xMargin,
00702 r.y() + d_data->yMargin + slo,
00703 sliderWidth,
00704 r.height() - 2 * d_data->yMargin - 2 * slo);
00705
00706 x = d_data->sliderRect.x() - d_data->scaleDist;
00707 y = d_data->sliderRect.y() + sld1;
00708
00709 break;
00710
00711 case NoScale:
00712 default:
00713 d_data->sliderRect.setRect(
00714 r.x() + r.width() - sliderWidth - d_data->xMargin,
00715 r.y() + d_data->yMargin + slo,
00716 sliderWidth,
00717 r.height() - 2 * d_data->yMargin - 2 * slo);
00718
00719 x = 0;
00720 y = d_data->sliderRect.y() + sld1;
00721
00722 break;
00723 }
00724 length = d_data->sliderRect.height() - (sld1 + sld2);
00725 }
00726
00727 scaleDraw()->move(x, y);
00728 scaleDraw()->setLength(length);
00729
00730 d_data->map.setPaintXInterval(scaleDraw()->map().p1(),
00731 scaleDraw()->map().p2());
00732
00733 if ( update_geometry )
00734 {
00735 d_data->sizeHintCache = QSize();
00736 updateGeometry();
00737 update();
00738 }
00739 }
00740
00742 void QwtSlider::valueChange()
00743 {
00744 QwtAbstractSlider::valueChange();
00745 update();
00746 }
00747
00748
00750 void QwtSlider::rangeChange()
00751 {
00752 d_data->map.setScaleInterval(minValue(), maxValue());
00753
00754 if (autoScale())
00755 rescale(minValue(), maxValue());
00756
00757 QwtAbstractSlider::rangeChange();
00758 layoutSlider();
00759 }
00760
00766 void QwtSlider::setMargins(int xMargin, int yMargin)
00767 {
00768 if ( xMargin < 0 )
00769 xMargin = 0;
00770 if ( yMargin < 0 )
00771 yMargin = 0;
00772
00773 if ( xMargin != d_data->xMargin || yMargin != d_data->yMargin )
00774 {
00775 d_data->xMargin = xMargin;
00776 d_data->yMargin = yMargin;
00777 layoutSlider();
00778 }
00779 }
00780
00784 void QwtSlider::setBgStyle(BGSTYLE st)
00785 {
00786 d_data->bgStyle = st;
00787 layoutSlider();
00788 }
00789
00793 QwtSlider::BGSTYLE QwtSlider::bgStyle() const
00794 {
00795 return d_data->bgStyle;
00796 }
00797
00801 int QwtSlider::thumbLength() const
00802 {
00803 return d_data->thumbLength;
00804 }
00805
00809 int QwtSlider::thumbWidth() const
00810 {
00811 return d_data->thumbWidth;
00812 }
00813
00817 int QwtSlider::borderWidth() const
00818 {
00819 return d_data->borderWidth;
00820 }
00821
00825 QSize QwtSlider::sizeHint() const
00826 {
00827 return minimumSizeHint();
00828 }
00829
00835 QSize QwtSlider::minimumSizeHint() const
00836 {
00837 if (!d_data->sizeHintCache.isEmpty())
00838 return d_data->sizeHintCache;
00839
00840 int sliderWidth = d_data->thumbWidth;
00841 if (d_data->bgStyle & BgTrough)
00842 sliderWidth += 2 * d_data->borderWidth;
00843
00844 int w = 0, h = 0;
00845 if (d_data->scalePos != NoScale)
00846 {
00847 int d1, d2;
00848 scaleDraw()->getBorderDistHint(font(), d1, d2);
00849 int msMbd = qwtMax(d1, d2);
00850
00851 int mbd = d_data->thumbLength / 2;
00852 if (d_data->bgStyle & BgTrough)
00853 mbd += d_data->borderWidth;
00854
00855 if ( mbd < msMbd )
00856 mbd = msMbd;
00857
00858 const int sdExtent = scaleDraw()->extent( QPen(), font() );
00859 const int sdLength = scaleDraw()->minLength( QPen(), font() );
00860
00861 h = sliderWidth + sdExtent + d_data->scaleDist;
00862 w = sdLength - 2 * msMbd + 2 * mbd;
00863 }
00864 else
00865 {
00866 w = 200;
00867 h = sliderWidth;
00868 }
00869
00870 if ( orientation() == Qt::Vertical )
00871 qSwap(w, h);
00872
00873 w += 2 * d_data->xMargin;
00874 h += 2 * d_data->yMargin;
00875
00876 d_data->sizeHintCache = QSize(w, h);
00877 return d_data->sizeHintCache;
00878 }