Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

qwt_slider.cpp

00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
00002  * Qwt Widget Library
00003  * Copyright (C) 1997   Josef Wilgen
00004  * Copyright (C) 2002   Uwe Rathmann
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the Qwt License, Version 1.0
00008  *****************************************************************************/
00009 
00010 // vim: expandtab
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       Scale and values might have different maps. This is
00039       confusing and I can't see strong arguments for such
00040       a feature. TODO ...
00041      */
00042     QwtScaleMap map; // linear 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         // enforce a valid combination of scale position and orientation
00111         if ((d_data->scalePos == Bottom) || (d_data->scalePos == Top))
00112             d_data->scalePos = None;
00113         // adopt the policy of layoutSlider (None lays out like Left)
00114         if (d_data->scalePos == Right)
00115            align = QwtScaleDraw::RightScale;
00116         else
00117            align = QwtScaleDraw::LeftScale;
00118     }
00119     else
00120     {
00121         // enforce a valid combination of scale position and orientation
00122         if ((d_data->scalePos == Left) || (d_data->scalePos == Right))
00123             d_data->scalePos = None;
00124         // adopt the policy of layoutSlider (None lays out like Bottom)
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 // if (o == Qt::Vertical)
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++; // shade line points one pixel below
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 // Vertical
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: // like Bottom, but no scale. See QwtSlider().
00584             default:   // inconsistent orientation and scale position
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 // if (orientation() == Qt::Vertical
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: // like Left, but no scale. See QwtSlider().
00630             default:   // inconsistent orientation and scale position
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(); // invalidate
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  // no scale
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 }

Generated on Mon Jan 30 22:16:26 2006 for Qwt User's Guide by  doxygen 1.4.4