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:

Generated on Sun Nov 21 11:12:44 2004 for Qwt User's Guide by doxygen 1.3.5