# qwt_panner.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 <qpainter.h>
    00013 #include <qpixmap.h>
    00014 #include <qevent.h>
    00015 #include <qframe.h>
    00016 #include <qcursor.h>
    00017 #if QT_VERSION < 0x040000
    00018 #include <qobjectlist.h>
    00019 #endif
    00020 #include "qwt_picker.h"
    00021 #include "qwt_array.h"
    00022 #include "qwt_panner.h"
    00023
    00024 static QwtArray<QwtPicker *> activePickers(QWidget *w)
    00025 {
    00026     QwtArray<QwtPicker *> pickers;
    00027
    00028 #if QT_VERSION >= 0x040000
    00029     QObjectList children = w->children();
    00030     for ( int i = 0; i < children.size(); i++ )
    00031     {
    00032         QObject *obj = children[i];
    00033         if ( obj->inherits("QwtPicker") )
    00034         {
    00035             QwtPicker *picker = (QwtPicker *)obj;
    00036             if ( picker->isEnabled() )
    00037                 pickers += picker;
    00038         }
    00039     }
    00040 #else
    00041     QObjectList *children = (QObjectList *)w->children();
    00042     if ( children )
    00043     {
    00044         for ( QObjectListIterator it(*children); it.current(); ++it )
    00045         {
    00046             QObject *obj = (QObject *)it.current();
    00047             if ( obj->inherits("QwtPicker") )
    00048             {
    00049                 QwtPicker *picker = (QwtPicker *)obj;
    00050                 if ( picker->isEnabled() )
    00051                 {
    00052                     pickers.resize(pickers.size() + 1);
    00053                     pickers[int(pickers.size()) - 1] = picker;
    00054                 }
    00055             }
    00056         }
    00057     }
    00058 #endif
    00059
    00060     return pickers;
    00061 }
    00062
    00063 class QwtPanner::PrivateData
    00064 {
    00065 public:
    00066     PrivateData():
    00067         button(Qt::LeftButton),
    00068         buttonState(Qt::NoButton),
    00069         abortKey(Qt::Key_Escape),
    00070         abortKeyState(Qt::NoButton),
    00071 #ifndef QT_NO_CURSOR
    00072         cursor(NULL),
    00073         restoreCursor(NULL),
    00074         hasCursor(false),
    00075 #endif
    00076         isEnabled(false)
    00077     {
    00078 #if QT_VERSION >= 0x040000
    00079         orientations = Qt::Vertical | Qt::Horizontal;
    00080 #else
    00081         orientations[Qt::Vertical] = true;
    00082         orientations[Qt::Horizontal] = true;
    00083 #endif
    00084     }
    00085
    00086     ~PrivateData()
    00087     {
    00088 #ifndef QT_NO_CURSOR
    00089         delete cursor;
    00090         delete restoreCursor;
    00091 #endif
    00092     }
    00093
    00094     int button;
    00095     int buttonState;
    00096     int abortKey;
    00097     int abortKeyState;
    00098
    00099     QPoint initialPos;
    00100     QPoint pos;
    00101
    00102     QPixmap pixmap;
    00103 #ifndef QT_NO_CURSOR
    00104     QCursor *cursor;
    00105     QCursor *restoreCursor;
    00106     bool hasCursor;
    00107 #endif
    00108     bool isEnabled;
    00109 #if QT_VERSION >= 0x040000
    00110     Qt::Orientations orientations;
    00111 #else
    00112     bool orientations[2];
    00113 #endif
    00114 };
    00115
    00121 QwtPanner::QwtPanner(QWidget *parent):
    00122     QWidget(parent)
    00123 {
    00124     d_data = new PrivateData();
    00125
    00126 #if QT_VERSION >= 0x040000
    00127     setAttribute(Qt::WA_TransparentForMouseEvents);
    00128     setAttribute(Qt::WA_NoSystemBackground);
    00129     setFocusPolicy(Qt::NoFocus);
    00130 #else
    00131     setBackgroundMode(Qt::NoBackground);
    00132     setFocusPolicy(QWidget::NoFocus);
    00133 #endif
    00134     hide();
    00135
    00136     setEnabled(true);
    00137 }
    00138
    00140 QwtPanner::~QwtPanner()
    00141 {
    00142     delete d_data;
    00143 }
    00144
    00149 void QwtPanner::setMouseButton(int button, int buttonState)
    00150 {
    00151     d_data->button = button;
    00152     d_data->buttonState = buttonState;
    00153 }
    00154
    00156 void QwtPanner::getMouseButton(int &button, int &buttonState) const
    00157 {
    00158     button = d_data->button;
    00159     buttonState = d_data->buttonState;
    00160 }
    00161
    00166 void QwtPanner::setAbortKey(int key, int state)
    00167 {
    00168     d_data->abortKey = key;
    00169     d_data->abortKeyState = state;
    00170 }
    00171
    00173 void QwtPanner::getAbortKey(int &key, int &state) const
    00174 {
    00175     key = d_data->abortKey;
    00176     state = d_data->abortKeyState;
    00177 }
    00178
    00187 #ifndef QT_NO_CURSOR
    00188 void QwtPanner::setCursor(const QCursor &cursor)
    00189 {
    00190     d_data->cursor = new QCursor(cursor);
    00191 }
    00192 #endif
    00193
    00198 #ifndef QT_NO_CURSOR
    00199 const QCursor QwtPanner::cursor() const
    00200 {
    00201     if ( d_data->cursor )
    00202         return *d_data->cursor;
    00203
    00204     if ( parentWidget() )
    00205         return parentWidget()->cursor();
    00206
    00207     return QCursor();
    00208 }
    00209 #endif
    00210
    00220 void QwtPanner::setEnabled(bool on)
    00221 {
    00222     if ( d_data->isEnabled != on )
    00223     {
    00224         d_data->isEnabled = on;
    00225
    00226         QWidget *w = parentWidget();
    00227         if ( w )
    00228         {
    00229             if ( d_data->isEnabled )
    00230             {
    00231                 w->installEventFilter(this);
    00232             }
    00233             else
    00234             {
    00235                 w->removeEventFilter(this);
    00236                 hide();
    00237             }
    00238         }
    00239     }
    00240 }
    00241
    00242 #if QT_VERSION >= 0x040000
    00243
    00249 void QwtPanner::setOrientations(Qt::Orientations o)
    00250 {
    00251     d_data->orientations = o;
    00252 }
    00253
    00255 Qt::Orientations QwtPanner::orientations() const
    00256 {
    00257     return d_data->orientations;
    00258 }
    00259
    00260 #else
    00261 void QwtPanner::enableOrientation(Qt::Orientation o, bool enable)
    00262 {
    00263     if ( o == Qt::Vertical || o == Qt::Horizontal )
    00264         d_data->orientations[o] = enable;
    00265 }
    00266 #endif
    00267
    00272 bool QwtPanner::isOrientationEnabled(Qt::Orientation o) const
    00273 {
    00274 #if QT_VERSION >= 0x040000
    00275     return d_data->orientations & o;
    00276 #else
    00277     if ( o == Qt::Vertical || o == Qt::Horizontal )
    00278         return d_data->orientations[o];
    00279     return false;
    00280 #endif
    00281 }
    00282
    00287 bool QwtPanner::isEnabled() const
    00288 {
    00289     return d_data->isEnabled;
    00290 }
    00291
    00300 void QwtPanner::paintEvent(QPaintEvent *pe)
    00301 {
    00302     QPixmap pm(size());
    00303
    00304     QPainter painter(&pm);
    00305
    00306     const QColor bg =
    00307 #if QT_VERSION < 0x040000
    00308         parentWidget()->palette().color(
    00309             QPalette::Normal, QColorGroup::Background);
    00310 #else
    00311         parentWidget()->palette().color(
    00312             QPalette::Normal, QPalette::Background);
    00313 #endif
    00314
    00315     painter.setPen(Qt::NoPen);
    00316     painter.setBrush(QBrush(bg));
    00317     painter.drawRect(0, 0, pm.width(), pm.height());
    00318
    00319     int dx = d_data->pos.x() - d_data->initialPos.x();
    00320     int dy = d_data->pos.y() - d_data->initialPos.y();
    00321
    00322     QRect r(0, 0, d_data->pixmap.width(), d_data->pixmap.height());
    00323     r.moveCenter(QPoint(r.center().x() + dx, r.center().y() + dy));
    00324
    00325     painter.drawPixmap(r, d_data->pixmap);
    00326     painter.end();
    00327
    00328     painter.begin(this);
    00329     painter.setClipRegion(pe->region());
    00330     painter.drawPixmap(0, 0, pm);
    00331 }
    00332
    00341 bool QwtPanner::eventFilter(QObject *o, QEvent *e)
    00342 {
    00343     if ( o == NULL || o != parentWidget() )
    00344         return false;
    00345
    00346     switch(e->type())
    00347     {
    00348         case QEvent::MouseButtonPress:
    00349         {
    00350             widgetMousePressEvent((QMouseEvent *)e);
    00351             break;
    00352         }
    00353         case QEvent::MouseMove:
    00354         {
    00355             widgetMouseMoveEvent((QMouseEvent *)e);
    00356             break;
    00357         }
    00358         case QEvent::MouseButtonRelease:
    00359         {
    00360             widgetMouseReleaseEvent((QMouseEvent *)e);
    00361             break;
    00362         }
    00363         case QEvent::KeyPress:
    00364         {
    00365             widgetKeyPressEvent((QKeyEvent *)e);
    00366             break;
    00367         }
    00368         case QEvent::KeyRelease:
    00369         {
    00370             widgetKeyReleaseEvent((QKeyEvent *)e);
    00371             break;
    00372         }
    00373         case QEvent::Paint:
    00374         {
    00375             if ( isVisible() )
    00376                 return true;
    00377             break;
    00378         }
    00379         default:;
    00380     }
    00381
    00382     return false;
    00383 }
    00384
    00392 void QwtPanner::widgetMousePressEvent(QMouseEvent *me)
    00393 {
    00394     if ( me->button() != d_data->button )
    00395         return;
    00396
    00397     QWidget *w = parentWidget();
    00398     if ( w == NULL )
    00399         return;
    00400
    00401 #if QT_VERSION < 0x040000
    00402     if ( (me->state() & Qt::KeyButtonMask) !=
    00403         (d_data->buttonState & Qt::KeyButtonMask) )
    00404 #else
    00405     if ( (me->modifiers() & Qt::KeyboardModifierMask) !=
    00406         (int)(d_data->buttonState & Qt::KeyboardModifierMask) )
    00407 #endif
    00408     {
    00409         return;
    00410     }
    00411
    00412 #ifndef QT_NO_CURSOR
    00413     showCursor(true);
    00414 #endif
    00415
    00416     d_data->initialPos = d_data->pos = me->pos();
    00417
    00418     QRect cr = parentWidget()->rect();
    00419     if ( parentWidget()->inherits("QFrame") )
    00420     {
    00421         const QFrame* frame = (QFrame*)parentWidget();
    00422         cr = frame->contentsRect();
    00423     }
    00424     setGeometry(cr);
    00425
    00426     // We don't want to grab the picker !
    00427     QwtArray<QwtPicker *> pickers = activePickers(parentWidget());
    00428     for ( int i = 0; i < (int)pickers.size(); i++ )
    00429         pickers[i]->setEnabled(false);
    00430
    00431     d_data->pixmap = QPixmap::grabWidget(parentWidget(),
    00432         cr.x(), cr.y(), cr.width(), cr.height());
    00433
    00434     for ( int i = 0; i < (int)pickers.size(); i++ )
    00435         pickers[i]->setEnabled(true);
    00436
    00437     show();
    00438 }
    00439
    00446 void QwtPanner::widgetMouseMoveEvent(QMouseEvent *me)
    00447 {
    00448     if ( !isVisible() )
    00449         return;
    00450
    00451     QPoint pos = me->pos();
    00452     if ( !isOrientationEnabled(Qt::Horizontal) )
    00453         pos.setX(d_data->initialPos.x());
    00454     if ( !isOrientationEnabled(Qt::Vertical) )
    00455         pos.setY(d_data->initialPos.y());
    00456
    00457     if ( pos != d_data->pos && rect().contains(pos) )
    00458     {
    00459         d_data->pos = pos;
    00460         update();
    00461
    00462         emit moved(d_data->pos.x() - d_data->initialPos.x(),
    00463             d_data->pos.y() - d_data->initialPos.y());
    00464     }
    00465 }
    00466
    00474 void QwtPanner::widgetMouseReleaseEvent(QMouseEvent *me)
    00475 {
    00476     if ( isVisible() )
    00477     {
    00478         hide();
    00479 #ifndef QT_NO_CURSOR
    00480         showCursor(false);
    00481 #endif
    00482
    00483         QPoint pos = me->pos();
    00484         if ( !isOrientationEnabled(Qt::Horizontal) )
    00485             pos.setX(d_data->initialPos.x());
    00486         if ( !isOrientationEnabled(Qt::Vertical) )
    00487             pos.setY(d_data->initialPos.y());
    00488
    00489         d_data->pixmap = QPixmap();
    00490         d_data->pos = pos;
    00491
    00492         if ( d_data->pos != d_data->initialPos )
    00493         {
    00494             emit panned(d_data->pos.x() - d_data->initialPos.x(),
    00495                 d_data->pos.y() - d_data->initialPos.y());
    00496         }
    00497     }
    00498 }
    00499
    00506 void QwtPanner::widgetKeyPressEvent(QKeyEvent *ke)
    00507 {
    00508     if ( ke->key() == d_data->abortKey )
    00509     {
    00510         const bool matched =
    00511 #if QT_VERSION < 0x040000
    00512             (ke->state() & Qt::KeyButtonMask) ==
    00513                 (d_data->abortKeyState & Qt::KeyButtonMask);
    00514 #else
    00515             (ke->modifiers() & Qt::KeyboardModifierMask) ==
    00516                 (int)(d_data->abortKeyState & Qt::KeyboardModifierMask);
    00517 #endif
    00518         if ( matched )
    00519         {
    00520             hide();
    00521 #ifndef QT_NO_CURSOR
    00522             showCursor(false);
    00523 #endif
    00524             d_data->pixmap = QPixmap();
    00525         }
    00526     }
    00527 }
    00528
    00535 void QwtPanner::widgetKeyReleaseEvent(QKeyEvent *)
    00536 {
    00537 }
    00538
    00539 #ifndef QT_NO_CURSOR
    00540 void QwtPanner::showCursor(bool on)
    00541 {
    00542     if ( on == d_data->hasCursor )
    00543         return;
    00544
    00545     QWidget *w = parentWidget();
    00546     if ( w == NULL || d_data->cursor == NULL )
    00547         return;
    00548
    00549     d_data->hasCursor = on;
    00550
    00551     if ( on )
    00552     {
    00553 #if QT_VERSION < 0x040000
    00554         if ( w->testWState(WState_OwnCursor) )
    00555 #else
    00556         if ( w->testAttribute(Qt::WA_SetCursor) )
    00557 #endif
    00558         {
    00559             delete d_data->restoreCursor;
    00560             d_data->restoreCursor = new QCursor(w->cursor());
    00561         }
    00562         w->setCursor(*d_data->cursor);
    00563     }
    00564     else
    00565     {
    00566         if ( d_data->restoreCursor )
    00567         {
    00568             w->setCursor(*d_data->restoreCursor);
    00569             delete d_data->restoreCursor;
    00570             d_data->restoreCursor = NULL;
    00571         }
    00572         else
    00573             w->unsetCursor();
    00574     }
    00575 }
    00576 #endif