QtWheel.cc

00001 /*===========================================================================*\
00002  *                                                                           *
00003  *                              OpenFlipper                                  *
00004  *      Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen      *
00005  *                           www.openflipper.org                             *
00006  *                                                                           *
00007  *---------------------------------------------------------------------------*
00008  *  This file is part of OpenFlipper.                                        *
00009  *                                                                           *
00010  *  OpenFlipper is free software: you can redistribute it and/or modify      *
00011  *  it under the terms of the GNU Lesser General Public License as           *
00012  *  published by the Free Software Foundation, either version 3 of           *
00013  *  the License, or (at your option) any later version with the              *
00014  *  following exceptions:                                                    *
00015  *                                                                           *
00016  *  If other files instantiate templates or use macros                       *
00017  *  or inline functions from this file, or you compile this file and         *
00018  *  link it with other files to produce an executable, this file does        *
00019  *  not by itself cause the resulting executable to be covered by the        *
00020  *  GNU Lesser General Public License. This exception does not however       *
00021  *  invalidate any other reasons why the executable file might be            *
00022  *  covered by the GNU Lesser General Public License.                        *
00023  *                                                                           *
00024  *  OpenFlipper is distributed in the hope that it will be useful,           *
00025  *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
00026  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
00027  *  GNU Lesser General Public License for more details.                      *
00028  *                                                                           *
00029  *  You should have received a copy of the GNU LesserGeneral Public          *
00030  *  License along with OpenFlipper. If not,                                  *
00031  *  see <http://www.gnu.org/licenses/>.                                      *
00032  *                                                                           *
00033 \*===========================================================================*/
00034 
00035 /*===========================================================================*\
00036  *                                                                           *
00037  *   $Revision: 6743 $                                                       *
00038  *   $Author: moebius $                                                      *
00039  *   $Date: 2009-08-05 11:03:10 +0200 (Mi, 05. Aug 2009) $                   *
00040  *                                                                           *
00041 \*===========================================================================*/
00042 
00043 
00044 
00045 //=============================================================================
00046 //
00047 //  CLASS QtWheel - IMPLEMENTATION
00048 //
00049 //=============================================================================
00050 
00051 //== INCLUDES =================================================================
00052 
00053 #include "QtWheel.hh"
00054 
00055 #include <math.h>
00056 #include <float.h>
00057 #include <iostream>
00058 #include <algorithm>
00059 
00060 //#include <QDrawutil>
00061 
00062 #include <QEvent>
00063 #include <QPainter>
00064 #include <QMenu>
00065 #include <QPixmap>
00066 #include <QTimer>
00067 #include <QCursor>
00068 #include <QBrush>
00069 #include <QPaintEvent>
00070 #include <QKeyEvent>
00071 #include <QResizeEvent>
00072 #include <QMouseEvent>
00073 
00074 
00075 //== NAMESPACES ===============================================================
00076 
00077 
00078 namespace ACG {
00079 namespace QtWidgets {
00080 
00081 
00082 //== IMPLEMENTATION ==========================================================
00083 
00084 
00085 QtWheel::QtWheel(QWidget* _parent,
00086                const char* /* _name */ ,
00087                Orientation _orientation)
00088   : QFrame(_parent)
00089 {
00090   angle_       = 0.0;
00091   lastAngle_   = 0.0;
00092   gear_        = 1.0;
00093   gearShift_   = 0;
00094   // size_ will be set by redrawPixmap()
00095 
00096   ticks_       = 36;
00097   marker_      = false;
00098   orientation_ = _orientation;
00099   dragging_    = false;
00100   tracking_    = true;
00101 
00102   palette_     = palette();
00103   palette_.setColor( QPalette::Dark,  QColor(0,0,0));
00104 
00105   setFrameStyle( QtWheel::Panel | QtWheel::Raised );
00106   setLineWidth(2);
00107 
00108   setContextMenuPolicy ( Qt::CustomContextMenu );
00109 
00110   connect (this, SIGNAL (customContextMenuRequested ( const QPoint & ) ),
00111            this, SLOT( slotCustomContextMenuRequested ( const QPoint & ) ));
00112 
00113 }
00114 
00115 QtWheel::~QtWheel() {
00116 }
00117 
00118 //----------------------------------------------------------------------------
00119 
00120 void QtWheel::mousePressEvent(QMouseEvent* _e)
00121 {
00122   if (_e->button()==Qt::LeftButton) {
00123     pos_=_e->pos();
00124     dragging_=true;
00125     lastAngle_=angle_;
00126   }
00127 }
00128 
00129 void QtWheel::mouseReleaseEvent(QMouseEvent* _e)
00130 {
00131   if (_e->button()==Qt::LeftButton)
00132   {
00133     dragging_=false;
00134 
00135 //     turn(_e->pos());
00136 //     emit angleChangedTo(angle_);
00137 //     emit angleChangedBy(angle_-lastAngle_);
00138   }
00139 }
00140 
00141 
00142 void QtWheel::mouseMoveEvent(QMouseEvent* _e)
00143 {
00144   if (_e->buttons()&Qt::LeftButton)
00145   {
00146     float dAngle=turn(_e->pos());
00147 
00148     if (tracking_ && dAngle!=0.0) { // 0.0 is explicitly returned
00149       lastAngle_=angle_-dAngle;
00150 
00151       emit angleChangedTo(angle_);
00152       emit angleChangedBy(dAngle);
00153     }
00154   }
00155 }
00156 
00157 
00158 double QtWheel::turn(const QPoint& _pos)
00159 {
00160   QPoint dPos=(_pos-pos_);
00161   pos_=_pos;
00162 
00163   int d = orientation_== Horizontal ? dPos.x() : dPos.y();
00164 
00165   double dAngle=0.0;
00166 
00167   if (d!=0) {
00168     // full width/height = 180 deg for gear()==1
00169     dAngle=double(d)/double(size_)*M_PI*gear_;
00170     angle_+=dAngle;
00171 
00172     redrawPixmap();
00173     repaint();
00174   }
00175   return dAngle;
00176 }
00177 
00178 //----------------------------------------------------------------------------
00179 
00180 void QtWheel::mouseDoubleClickEvent(QMouseEvent* _e) {
00181   if (_e->button()==Qt::LeftButton) {
00182     int sz,x;
00183     if (orientation_== Horizontal) {
00184       sz=width();  x=_e->x();
00185     }
00186     else {
00187       sz=height(); x=_e->y();
00188     }
00189 
00190     if (x<sz/2) {
00191       if (gearShift_<8) {
00192         ++gearShift_;
00193         gear_*=2.0;
00194 
00195         redrawPixmap();
00196         repaint();
00197 
00198         emit gearUp();
00199       }
00200     }
00201     else {
00202       if (gearShift_>-8) {
00203         --gearShift_;
00204         gear_/=2.0;
00205 
00206         redrawPixmap();
00207         repaint();
00208 
00209         emit gearDown();
00210       }
00211     }
00212   }
00213 }
00214 
00215 //----------------------------------------------------------------------------
00216 
00217 void QtWheel::keyPressEvent(QKeyEvent* _e) {
00218 
00219   //
00220   // This does not work! Do we really need/want keyboard input???
00221   //
00222 
00223   if (dragging_)
00224     return;
00225 
00226   double dAngle=0.0;
00227 
00228   if (!_e->isAutoRepeat())
00229     lastAngle_=angle_;
00230 
00231   switch (_e->key()) {
00232     case Qt::Key_Left:
00233     case Qt::Key_Up: {
00234       dAngle= -M_PI/double(ticks_)*gear_;
00235     }
00236     break;
00237 
00238     case Qt::Key_Right:
00239     case Qt::Key_Down: {
00240       dAngle= +M_PI/double(ticks_)*gear_;
00241     }
00242     break;
00243 
00244     default: return;
00245   }
00246 
00247   if (tracking_)
00248     lastAngle_=angle_;
00249 
00250   angle_+=dAngle;
00251 
00252   redrawPixmap();
00253   repaint();
00254 
00255   if (tracking_) {
00256     emit angleChangedTo(angle_);
00257     emit angleChangedBy(angle_-lastAngle_);
00258   }
00259 }
00260 
00261 void QtWheel::keyReleaseEvent(QKeyEvent* _e) {
00262   switch (_e->key()) {
00263     case Qt::Key_Left:
00264     case Qt::Key_Up:
00265     case Qt::Key_Right:
00266     case Qt::Key_Down: {
00267       if (!tracking_) {
00268         emit angleChangedTo(angle_);
00269         emit angleChangedBy(angle_-lastAngle_);
00270       }
00271     };
00272     break;
00273 
00274     default: return;
00275   }
00276 }
00277 
00278 //----------------------------------------------------------------------------
00279 
00280 void QtWheel::resizeEvent(QResizeEvent* _e) {
00281   QFrame::resizeEvent(_e);
00282   redrawPixmap();
00283 }
00284 
00285 void QtWheel::paintEvent(QPaintEvent* _e) {
00286   if (isVisible()) {
00287     QFrame::paintEvent(_e);
00288 
00289 
00290     QPainter painter(this);
00291     QRect r=contentsRect();
00292 
00294     painter.drawPixmap( r.left(), r.top(), pixmap_ );
00295 
00296   }
00297 }
00298 
00299 //----------------------------------------------------------------------------
00300 
00301 void QtWheel::redrawPixmap() {
00302  QRect r=contentsRect();
00303 
00304  if (r.width()<=0 || r.height()<=0) {
00305    pixmap_ = QPixmap( 0, 0 );
00306    return;
00307  }
00308 
00309  if (pixmap_.size()!=r.size())
00310    pixmap_ = QPixmap(r.size());
00311 
00312   QPainter paint;
00313 
00314   paint.begin( &pixmap_);
00315   pixmap_.fill( palette().background().color() );
00316 
00317   // coords of wheel frame
00318   QRect contents = contentsRect();
00319   contents.moveTopLeft(QPoint(0,0)); // transform to pixmap coord sys
00320 
00321   QPen pen(Qt::black, 1);
00322   paint.setPen(pen);
00323 
00324   if (orientation_ == Horizontal) {
00325 
00326     shrinkRect(contents, 3, 2);
00327 
00328     // draw a black frame
00329     paint.drawRect(contents);
00330     shrinkRect(contents, 1, 0);
00331     paint.drawRect(contents);
00332     shrinkRect(contents, 3, 2);
00333 
00334     int x0 = contents.left();
00335     int y0 = contents.top();
00336     int w0 = contents.width();
00337     int h0 = contents.height();
00338 
00339     size_=w0;
00340 
00341     if (gearShift_>0) {
00342       QBrush b; b.setColor(QColor(Qt::red)); b.setStyle(Qt::SolidPattern);
00343       int w=std::min(4*gearShift_,w0-8);
00344       paint.fillRect(x0+8,y0-1,w,h0+2,b);
00345     }
00346     else if (gearShift_<0) {
00347       QBrush b; b.setColor(QColor(Qt::blue));
00348       int w=std::min(-4*gearShift_,w0-8); b.setStyle(Qt::SolidPattern);
00349       paint.fillRect(x0+w0-w-8,y0-1,w,h0+2,b);
00350     }
00351 
00352     // draw the wheel
00353     double step = 2 * M_PI / (double) ticks_;
00354     for (int i = 0; i < ticks_; i++) {
00355       double x = sin(angle_ + i * step);
00356       double y = cos(angle_ + i * step);
00357       if (y>0) {
00358         qDrawShadeLine( &paint,
00359                         (int) (x0+(w0+x*w0)/2.0f), y0,
00360                         (int) (x0+(w0+x*w0)/2.0f), y0+h0,
00361                         palette_, false, 1, 1);
00362       }
00363     }
00364   }
00365 
00366   else if (orientation_ == Vertical) {
00367 
00368     shrinkRect(contents, 2, 3);
00369 
00370     // draw a black frame
00371     paint.drawRect(contents);
00372     shrinkRect(contents, 0, 1);
00373     paint.drawRect(contents);
00374     shrinkRect(contents, 2, 3);
00375 
00376 
00377     int x0 = contents.left();
00378     int y0 = contents.top();
00379     int w0 = contents.width();
00380     int h0 = contents.height();
00381 
00382     size_=h0;
00383 
00384     if (gearShift_>0) {
00385       QBrush b; b.setColor(QColor(Qt::red)); b.setStyle(Qt::SolidPattern);
00386       int h=-std::min(-4*gearShift_,h0-8);
00387       paint.fillRect(x0-1,y0+8,w0+2,h,b);
00388     }
00389     else if (gearShift_<0) {
00390       QBrush b; b.setColor(QColor(Qt::blue)); b.setStyle(Qt::SolidPattern);
00391       int h=-std::min(4*gearShift_,h0-8);
00392       paint.fillRect(x0-1,y0+h0-h-8,w0+2,h,b);
00393     }
00394 
00395     // draw the wheel
00396     double step = 2 * M_PI / (double) ticks_;
00397     for (int i = 0; i < ticks_; i++) {
00398       double x = sin(angle_ + i * step);
00399       double y = cos(angle_ + i * step);
00400       if (y>0) {
00401              qDrawShadeLine( &paint,
00402                         x0,    (int) (y0+(h0+x*h0)/2.0f),
00403                         x0+w0, (int) (y0+(h0+x*h0)/2.0f),
00404                         palette_, false, 1, 1);
00405       } // if y
00406     } // for ticks_
00407   } // if Vertical
00408   paint.end();
00409 }
00410 
00411 //-----------------------------------------------------------------------------
00412 
00413 void QtWheel::shrinkRect(QRect& _rect, int _dx, int _dy) {
00414   _rect.setLeft(_rect.left()+_dx);
00415   _rect.setRight(_rect.right()-_dx);
00416   _rect.setTop(_rect.top()+_dy); // dy -> -dy
00417   _rect.setBottom(_rect.bottom()-_dy);
00418 }
00419 
00420 //-----------------------------------------------------------------------------
00421 
00422 QSizePolicy QtWheel::sizePolicy() const
00423 {
00424   if (orientation_== Horizontal)
00425     return QSizePolicy(QSizePolicy::Preferred,
00426                        QSizePolicy::Minimum);
00427   else
00428     return QSizePolicy(QSizePolicy::Minimum,
00429                        QSizePolicy::Preferred);
00430 }
00431 
00432 //-----------------------------------------------------------------------------
00433 
00434 QSize QtWheel::sizeHint() const
00435 {
00436   if (orientation_==Horizontal)
00437     return QSize(120,20);
00438   else
00439     return QSize(20,120);
00440 }
00441 
00442 //-----------------------------------------------------------------------------
00443 
00444 
00445 double QtWheel::clip(double _angle) {
00446   return fmod(_angle,2*M_PI);
00447 }
00448 
00449 double QtWheel::deg(double _angle) {
00450   return _angle*180.0/M_PI;
00451 }
00452 
00453 //-----------------------------------------------------------------------------
00454 
00455 void QtWheel::slotCustomContextMenuRequested ( const QPoint & pos ) {
00456 
00457   QMenu* menu = new QMenu(this);
00458   QAction *hide = menu->addAction("Hide wheel");
00459   connect( hide, SIGNAL(triggered()) , this, SIGNAL(hideWheel()) );
00460   menu->popup( mapToGlobal(pos) );
00461 
00462 }
00463 
00464 
00465 //=============================================================================
00466 } // namespace QtWidgets
00467 } // namespace ACG
00468 //=============================================================================

acg pic Project OpenFlipper, ©  Computer Graphics Group, RWTH Aachen. Documentation generated using doxygen .