Main Page | Class Hierarchy | Alphabetical List | Class List | 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 <qstyle.h>
    00014 #include <qevent.h>
    00015 #include <qdrawutil.h>
    00016 #include <qpainter.h>
    00017 #include "qwt_paint_buffer.h"
    00018 #include "qwt_slider.h"
    00019
    00040 QwtSlider::QwtSlider(QWidget *parent, const char *name,
    00041         Qt::Orientation orient, ScalePos scalePos, BGSTYLE bgStyle):
    00042     QwtSliderBase(orient, parent, name, Qt::WRepaintNoErase|Qt::WResizeNoErase)
    00043 {
    00044     d_borderWidth = 2;
    00045     d_scaleDist = 4;
    00046     d_scalePos = scalePos;
    00047     d_xMargin = 0;
    00048     d_yMargin = 0;
    00049     d_bgStyle = bgStyle;
    00050
    00051     if (bgStyle == BgSlot)
    00052     {
    00053         d_thumbLength = 16;
    00054         d_thumbWidth = 30;
    00055     }
    00056     else
    00057     {
    00058         d_thumbLength = 31;
    00059         d_thumbWidth = 16;
    00060     }
    00061
    00062     d_sliderRect.setRect(0,0,8,8);
    00063
    00064     QwtScaleDraw::Orientation so;
    00065     if ( orientation() == Qt::Vertical )
    00066     {
    00067         // enforce a valid combination of scale position and orientation
    00068         if ((d_scalePos == Bottom) || (d_scalePos == Top))
    00069             d_scalePos = None;
    00070         // adopt the policy of layoutSlider (None lays out like Left)
    00071         if (d_scalePos == Right)
    00072            so = QwtScaleDraw::Right;
    00073         else
    00074            so = QwtScaleDraw::Left;
    00075     }
    00076     else
    00077     {
    00078         // enforce a valid combination of scale position and orientation
    00079         if ((d_scalePos == Left) || (d_scalePos == Right))
    00080             d_scalePos = None;
    00081         // adopt the policy of layoutSlider (None lays out like Bottom)
    00082         if (d_scalePos == Top)
    00083            so = QwtScaleDraw::Top;
    00084         else
    00085            so = QwtScaleDraw::Bottom;
    00086     }
    00087
    00088     scaleDraw()->setGeometry(0,0,100,so);
    00089 }
    00090
    00099 void QwtSlider::setOrientation(Qt::Orientation o)
    00100 {
    00101     if (o == Qt::Horizontal)
    00102     {
    00103         if ((d_scalePos == Left) || (d_scalePos == Right))
    00104             d_scalePos = None;
    00105     }
    00106     else // if (o == Qt::Vertical)
    00107     {
    00108         if ((d_scalePos == Bottom) || (d_scalePos == Top))
    00109             d_scalePos = None;
    00110     }
    00111     QwtSliderBase::setOrientation(o);
    00112     layoutSlider();
    00113 }
    00114
    00127 void QwtSlider::setScalePosition(ScalePos s)
    00128 {
    00129     d_scalePos = s;
    00130     if ((s == Bottom) || (s == Top))
    00131         setOrientation(Qt::Horizontal);
    00132     else if ((s == Left) || (s == Right))
    00133         setOrientation(Qt::Vertical);
    00134     else
    00135         layoutSlider();
    00136 }
    00137
    00139 QwtSlider::ScalePos QwtSlider::scalePosition() const
    00140 {
    00141     return d_scalePos;
    00142 }
    00143
    00148 void QwtSlider::setBorderWidth(int bd)
    00149 {
    00150     if ( bd < 0 )
    00151         bd = 0;
    00152
    00153     if ( bd != d_borderWidth )
    00154     {
    00155         d_borderWidth = bd;
    00156         layoutSlider();
    00157     }
    00158 }
    00159
    00164 void QwtSlider::setThumbLength(int thumbLength)
    00165 {
    00166     if ( thumbLength < 8 )
    00167         thumbLength = 8;
    00168
    00169     if ( thumbLength != d_thumbLength )
    00170     {
    00171         d_thumbLength = thumbLength;
    00172         layoutSlider();
    00173     }
    00174 }
    00175
    00180 void QwtSlider::setThumbWidth(int w)
    00181 {
    00182     if ( w < 4 )
    00183         w = 4;
    00184
    00185     if ( d_thumbWidth != w )
    00186     {
    00187         d_thumbWidth = w;
    00188         layoutSlider();
    00189     }
    00190 }
    00191
    00192
    00194 void QwtSlider::scaleChange()
    00195 {
    00196     if (!hasUserScale())
    00197     {
    00198         scaleDraw()->setScale(minValue(), maxValue(),
    00199             scaleMaxMajor(), scaleMaxMinor(),
    00200             scaleDraw()->scaleDiv().logScale());
    00201     }
    00202
    00203     layoutSlider();
    00204 }
    00205
    00206
    00208 void QwtSlider::fontChange(const QFont &f)
    00209 {
    00210     QwtSliderBase::fontChange( f );
    00211     layoutSlider();
    00212 }
    00213
    00215 void QwtSlider::drawSlider(QPainter *p, const QRect &r)
    00216 {
    00217     QRect cr(r);
    00218
    00219     if (d_bgStyle & BgTrough)
    00220     {
    00221         qDrawShadePanel(p, r.x(), r.y(),
    00222             r.width(), r.height(),
    00223             colorGroup(), TRUE, d_borderWidth,0);
    00224
    00225         cr.setRect(r.x() + d_borderWidth,
    00226             r.y() + d_borderWidth,
    00227             r.width() - 2 * d_borderWidth,
    00228             r.height() - 2 * d_borderWidth);
    00229
    00230         p->fillRect(cr.x(), cr.y(), cr.width(), cr.height(),
    00231             colorGroup().brush(QColorGroup::Mid));
    00232     }
    00233
    00234     if ( d_bgStyle & BgSlot)
    00235     {
    00236         int ws = 4;
    00237         int ds = d_thumbLength / 2 - 4;
    00238         if ( ds < 1 )
    00239             ds = 1;
    00240
    00241         QRect rSlot;
    00242         if (orientation() == Qt::Horizontal)
    00243         {
    00244             if ( cr.height() & 1 )
    00245                 ws++;
    00246             rSlot = QRect(cr.x() + ds,
    00247                     cr.y() + (cr.height() - ws) / 2,
    00248                     cr.width() - 2 * ds, ws);
    00249         }
    00250         else
    00251         {
    00252             if ( cr.width() & 1 )
    00253                 ws++;
    00254             rSlot = QRect(cr.x() + (cr.width() - ws) / 2,
    00255                     cr.y() + ds,
    00256                     ws, cr.height() - 2 * ds);
    00257         }
    00258         p->fillRect(rSlot.x(), rSlot.y(), rSlot.width(), rSlot.height(),
    00259             colorGroup().brush(QColorGroup::Dark));
    00260         qDrawShadePanel(p, rSlot.x(), rSlot.y(),
    00261             rSlot.width(), rSlot.height(), colorGroup(), TRUE, 1 ,0);
    00262
    00263     }
    00264
    00265     if ( isValid() )
    00266         drawThumb(p, cr, xyPosition(value()));
    00267 }
    00268
    00270 void QwtSlider::drawThumb(QPainter *p, const QRect &sliderRect, int pos)
    00271 {
    00272     pos++; // shade line points one pixel below
    00273     if (orientation() == Qt::Horizontal)
    00274     {
    00275         qDrawShadePanel(p, pos - d_thumbLength / 2,
    00276             sliderRect.y(), d_thumbLength, sliderRect.height(),
    00277             colorGroup(), FALSE, d_borderWidth,
    00278             &colorGroup().brush(QColorGroup::Button));
    00279
    00280         qDrawShadeLine(p, pos, sliderRect.y(),
    00281             pos, sliderRect.y() + sliderRect.height() - 2,
    00282             colorGroup(), TRUE, 1);
    00283     }
    00284     else // Vertical
    00285     {
    00286         qDrawShadePanel(p,sliderRect.x(), pos - d_thumbLength / 2,
    00287             sliderRect.width(), d_thumbLength,
    00288             colorGroup(),FALSE, d_borderWidth,
    00289             &colorGroup().brush(QColorGroup::Button));
    00290
    00291         qDrawShadeLine(p, sliderRect.x(), pos,
    00292             sliderRect.x() + sliderRect.width() - 2, pos,
    00293             colorGroup(), TRUE, 1);
    00294     }
    00295 }
    00296
    00298 int QwtSlider::xyPosition(double v) const
    00299 {
    00300     int pos;
    00301     if ( minValue() == scaleDraw()->d1() && maxValue() == scaleDraw()->d2() )
    00302     {
    00303         // We prefer to use the transformation of scaleDraw
    00304         // So ticks and marker are always in sync and we don't have
    00305         // to take care of rounding problems.
    00306
    00307         pos = scaleDraw()->transform(v);
    00308     }
    00309     else
    00310     {
    00311         // range and scaleDraw differ ? Sounds strange but
    00312         // might happen with logarithmic scales
    00313
    00314         const double f = (v - minValue()) / (maxValue() - minValue());
    00315         double dPos;
    00316         if ( orientation() == Qt::Horizontal )
    00317             dPos = scaleDraw()->i1() + f * (scaleDraw()->i2() - scaleDraw()->i1());
    00318         else
    00319             dPos = scaleDraw()->i1() - f * (scaleDraw()->i1() - scaleDraw()->i2());
    00320         pos = qRound(dPos);
    00321     }
    00322     return pos;
    00323 }
    00324
    00326 double QwtSlider::getValue(const QPoint &p)
    00327 {
    00328     double rv;
    00329
    00330     if ( minValue() == scaleDraw()->d1() && maxValue() == scaleDraw()->d2() )
    00331     {
    00332         rv = scaleDraw()->invTransform(
    00333             orientation() == Qt::Horizontal ? p.x() : p.y());
    00334     }
    00335     else
    00336     {
    00337         double pos;
    00338         double range;
    00339         if ( orientation() == Qt::Horizontal )
    00340         {
    00341             pos = p.x() - scaleDraw()->i1();
    00342             range = scaleDraw()->i2() - scaleDraw()->i1();
    00343         }
    00344         else
    00345         {
    00346             pos = scaleDraw()->i1() - p.y();
    00347             range = scaleDraw()->i1() - scaleDraw()->i2();
    00348         }
    00349
    00350         rv = minValue() + pos / range * (maxValue() - minValue());
    00351     }
    00352
    00353     return(rv);
    00354 }
    00355
    00356
    00363 void QwtSlider::getScrollMode(const QPoint &p,
    00364     int &scrollMode, int &direction )
    00365 {
    00366     if (!d_sliderRect.contains(p))
    00367     {
    00368         scrollMode = ScrNone;
    00369         direction = 0;
    00370         return;
    00371     }
    00372
    00373     const int pos = ( orientation() == Qt::Horizontal ) ? p.x() : p.y();
    00374     const int markerPos = xyPosition(value());
    00375
    00376     if ((pos > markerPos - d_thumbLength / 2)
    00377         && (pos < markerPos + d_thumbLength / 2))
    00378     {
    00379         scrollMode = ScrMouse;
    00380         direction = 0;
    00381         return;
    00382     }
    00383
    00384     scrollMode = ScrPage;
    00385     direction = (pos > markerPos) ? 1 : -1;
    00386     if ( scaleDraw()->i1() > scaleDraw()->i2() )
    00387         direction = -direction;
    00388 }
    00389
    00391 void QwtSlider::paintEvent(QPaintEvent *e)
    00392 {
    00393     const QRect &ur = e->rect();
    00394     if ( ur.isValid() )
    00395     {
    00396         QwtPaintBuffer paintBuffer(this, ur);
    00397         draw(paintBuffer.painter(), ur);
    00398     }
    00399 }
    00400
    00402 void QwtSlider::draw(QPainter *painter, const QRect&)
    00403 {
    00404     if (d_scalePos != None)
    00405         scaleDraw()->draw(painter);
    00406
    00407     drawSlider(painter, d_sliderRect);
    00408     if ( hasFocus() )
    00409     {
    00410         const QRect rect = d_sliderRect;
    00411
    00412 #if QT_VERSION < 300
    00413         style().drawFocusRect(painter, rect, colorGroup());
    00414 #else
    00415         style().drawPrimitive(QStyle::PE_FocusRect, painter,
    00416             rect, colorGroup());
    00417 #endif
    00418     }
    00419 }
    00420
    00422 void QwtSlider::resizeEvent(QResizeEvent *)
    00423 {
    00424     layoutSlider( FALSE );
    00425 }
    00426
    00433 void QwtSlider::layoutSlider( bool update_geometry )
    00434 {
    00435     int sliderWidth = d_thumbWidth;
    00436     int sld1 = d_thumbLength / 2 - 1;
    00437     int sld2 = d_thumbLength / 2 + d_thumbLength % 2;
    00438     if ( d_bgStyle & BgTrough )
    00439     {
    00440         sliderWidth += 2 * d_borderWidth;
    00441         sld1 += d_borderWidth;
    00442         sld2 += d_borderWidth;
    00443     }
    00444
    00445     int scd = 0;
    00446     if ( d_scalePos != None )
    00447     {
    00448         int d1, d2;
    00449         scaleDraw()->minBorderDist(fontMetrics(), d1, d2);
    00450         scd = QMAX(d1, d2);
    00451     }
    00452
    00453     int slo = scd - sld1;
    00454     if ( slo < 0 )
    00455         slo = 0;
    00456
    00457     const QRect r = rect();
    00458     if (orientation() == Qt::Horizontal)
    00459     {
    00460         switch (d_scalePos)
    00461         {
    00462         case Top:
    00463             d_sliderRect.setRect(
    00464         r.x() + d_xMargin + slo,
    00465                 r.y() + r.height() -
    00466                 d_yMargin - sliderWidth,
    00467                 r.width() - 2 * d_xMargin - 2 * slo,
    00468                 sliderWidth);
    00469             scaleDraw()->setGeometry(
    00470         d_sliderRect.x() + sld1,
    00471                 d_sliderRect.y() - d_scaleDist,
    00472                 d_sliderRect.width() - sld1 - sld2,
    00473                 QwtScaleDraw::Top);
    00474             break;
    00475
    00476         case Bottom:
    00477             d_sliderRect.setRect(
    00478         r.x() + d_xMargin + slo,
    00479                 r.y() + d_yMargin,
    00480                 r.width() - 2 * d_xMargin - 2 * slo,
    00481                 sliderWidth);
    00482             scaleDraw()->setGeometry(
    00483                 d_sliderRect.x() + sld1,
    00484                 d_sliderRect.y() + d_sliderRect.height() + d_scaleDist,
    00485                 d_sliderRect.width() - sld1 - sld2,
    00486                 QwtScaleDraw::Bottom);
    00487             break;
    00488
    00489         case None: // like Bottom, but no scale. See QwtSlider().
    00490         default:   // inconsistent orientation and scale position
    00491             // QwtScaleDraw is derived from QwtDiMap.
    00492             // The map serves to transform between coordinates and doubles.
    00493             d_sliderRect.setRect(
    00494                 r.x() + d_xMargin + slo,
    00495                 r.y() + d_yMargin,
    00496                 r.width() - 2 * d_xMargin - 2 * slo,
    00497                 sliderWidth);
    00498             scaleDraw()->setIntRange(
    00499                 d_sliderRect.x() + sld1,
    00500                 d_sliderRect.x() + d_sliderRect.width() - sld2 - 1);
    00501             break;
    00502         }
    00503     }
    00504     else // if (orientation() == Qt::Vertical
    00505     {
    00506         switch (d_scalePos)
    00507         {
    00508         case Right:
    00509             d_sliderRect.setRect(
    00510         r.x() + d_xMargin,
    00511                 r.y() + d_yMargin + slo,
    00512                 sliderWidth,
    00513                 r.height() - 2 * d_yMargin - 2 * slo);
    00514             scaleDraw()->setGeometry(
    00515         d_sliderRect.x() + d_sliderRect.width() + d_scaleDist,
    00516                 d_sliderRect.y() + sld1,
    00517                 d_sliderRect.height() - sld1 - sld2,
    00518                 QwtScaleDraw::Right);
    00519             break;
    00520
    00521         case Left:
    00522             d_sliderRect.setRect(
    00523         r.x() + r.width() - sliderWidth - d_xMargin,
    00524                 r.y() + d_yMargin + slo,
    00525                 sliderWidth,
    00526                 r.height() - 2 * d_yMargin - 2 * slo);
    00527             scaleDraw()->setGeometry(
    00528         d_sliderRect.x() - d_scaleDist,
    00529                 d_sliderRect.y() + sld1,
    00530                 d_sliderRect.height() - sld1 - sld2,
    00531                 QwtScaleDraw::Left);
    00532             break;
    00533
    00534         case None: // like Left, but no scale. See QwtSlider().
    00535         default:   // inconsistent orientation and scale position
    00536             // QwtScaleDraw is derived from QwtDiMap.
    00537             // The map serves to transform between coordinates and doubles.
    00538             d_sliderRect.setRect(
    00539                 r.x() + r.width() - sliderWidth - d_xMargin,
    00540                 r.y() + d_yMargin + slo,
    00541                 sliderWidth,
    00542                 r.height() - 2 * d_yMargin - 2 * slo);
    00543             scaleDraw()->setIntRange(
    00544                 d_sliderRect.y() + d_sliderRect.height() - sld2 - 1,
    00545                 d_sliderRect.y() + sld1);
    00546             break;
    00547         }
    00548     }
    00549
    00550     if ( update_geometry )
    00551     {
    00552         updateGeometry();
    00553         update();
    00554     }
    00555 }
    00556
    00558 void QwtSlider::valueChange()
    00559 {
    00560     QwtSliderBase::valueChange();
    00561     update();
    00562 }
    00563
    00564
    00566 void QwtSlider::rangeChange()
    00567 {
    00568     if (!hasUserScale())
    00569     {
    00570         scaleDraw()->setScale(minValue(), maxValue(),
    00571             scaleMaxMajor(), scaleMaxMinor(),
    00572             scaleDraw()->scaleDiv().logScale());
    00573     }
    00574
    00575     QwtSliderBase::rangeChange();
    00576     layoutSlider();
    00577 }
    00578
    00584 void QwtSlider::setMargins(int xMargin, int yMargin)
    00585 {
    00586     if ( xMargin < 0 )
    00587         xMargin = 0;
    00588     if ( yMargin < 0 )
    00589         yMargin = 0;
    00590
    00591     if ( xMargin != d_xMargin || yMargin != d_yMargin )
    00592     {
    00593         d_xMargin = xMargin;
    00594         d_yMargin = yMargin;
    00595         layoutSlider();
    00596     }
    00597 }
    00598
    00603 QSizePolicy QwtSlider::sizePolicy() const
    00604 {
    00605     QSizePolicy sp;
    00606     if ( orientation() == Qt::Horizontal )
    00607     {
    00608         sp.setHorData( QSizePolicy::MinimumExpanding );
    00609         sp.setVerData( QSizePolicy::Fixed );
    00610     }
    00611     else
    00612     {
    00613         sp.setHorData( QSizePolicy::Fixed );
    00614         sp.setVerData( QSizePolicy::MinimumExpanding );
    00615     }
    00616     return sp;
    00617 }
    00618
    00622 QSize QwtSlider::sizeHint() const
    00623 {
    00624     return minimumSizeHint();
    00625 }
    00626
    00632 QSize QwtSlider::minimumSizeHint() const
    00633 {
    00634     int w = 0, h = 0;
    00635
    00636     int sliderWidth = d_thumbWidth;
    00637     if (d_bgStyle & BgTrough)
    00638         sliderWidth += 2 * d_borderWidth;
    00639
    00640     if (d_scalePos != None)
    00641     {
    00642         int msWidth = scaleDraw()->minWidth( QPen(), fontMetrics() );
    00643         int msHeight = scaleDraw()->minHeight( QPen(), fontMetrics() );
    00644
    00645         int d1, d2;
    00646         scaleDraw()->minBorderDist(fontMetrics(), d1, d2);
    00647         int msMbd = QMAX(d1, d2);
    00648
    00649         int mbd = d_thumbLength / 2;
    00650         if (d_bgStyle & BgTrough)
    00651             mbd += d_borderWidth;
    00652
    00653         if ( mbd < msMbd )
    00654             mbd = msMbd;
    00655
    00656         if (orientation() == Qt::Vertical)
    00657         {
    00658             w = 2 * d_xMargin + sliderWidth + msWidth + d_scaleDist;
    00659             h = msHeight - 2 * msMbd + 2 * mbd + 2 * d_yMargin;
    00660         }
    00661         else
    00662         {
    00663             w = msWidth - 2 * msMbd + 2 * mbd + 2 * d_xMargin;
    00664             h = 2 * d_yMargin + sliderWidth  + msHeight + d_scaleDist;
    00665         }
    00666     }
    00667     else  // no scale
    00668     {
    00669         if (orientation() == Qt::Vertical)
    00670         {
    00671             w = 2 * d_xMargin + sliderWidth;
    00672             h = 200 + 2 * d_yMargin;
    00673         }
    00674         else
    00675         {
    00676             w = 200 + 2 * d_xMargin;
    00677             h = 2 * d_yMargin + sliderWidth;
    00678         }
    00679     }
    00680     return QSize(w,h);
    00681 }
    00682
    00683 // Local Variables:
    00684 // mode: C++
    00685 // c-file-style: "stroustrup"
    00686 // indent-tabs-mode: nil
    00687 // End: