qwt_picker.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 #include <qapplication.h>
00011 #include <qevent.h>
00012 #include <qpainter.h>
00013 #include <qframe.h>
00014 #include <qcursor.h>
00015 #include <qbitmap.h>
00016 #include "qwt_math.h"
00017 #include "qwt_painter.h"
00018 #include "qwt_picker_machine.h"
00019 #include "qwt_picker.h"
00020 #if QT_VERSION < 0x040000
00021 #include <qguardedptr.h>
00022 #else
00023 #include <qpointer.h>
00024 #endif
00025 
00026 #if QT_VERSION >= 0x040300
00027 /*
00028   With Qt >= 4.3 drawing of the tracker can be implemented in an
00029   easier, using the textRect as mask. Because calculating
00030   a QRegion from a QBitmask is expensive operation ( especially for
00031   longer texts !) this implementation is much faster too.
00032   Also the result looks much better.
00033 */
00034 #define USE_TRACKER_RECT_MASK
00035 #endif
00036 
00037 #ifndef USE_TRACKER_RECT_MASK
00038 #define USE_TRACKER_BACKGROUND
00039 #endif
00040 
00041 class QwtPicker::PrivateData
00042 {
00043 public:
00044     class PickerWidget: public QWidget
00045     {
00046     public:
00047         enum Type
00048         {
00049             RubberBand,
00050             Text
00051         };
00052         PickerWidget(QwtPicker *, QWidget *, Type);
00053         virtual void updateMask();
00054 
00055 #ifdef USE_TRACKER_BACKGROUND
00056         /*
00057            Internal flag, that is needed for tracker texts with a
00058            background. This flag has been introduced in Qwt 5.0.2 to avoid
00059            incompatible API changes. In Qwt 5.1 will be a cleaner solution.
00060          */
00061         mutable bool d_hasTrackerBackground;
00062 #endif
00063     protected:
00064         virtual void paintEvent(QPaintEvent *);
00065 
00066         QwtPicker *d_picker;
00067         Type d_type;
00068     };
00069 
00070     bool enabled;
00071 
00072     QwtPickerMachine *stateMachine;
00073 
00074     int selectionFlags;
00075     QwtPicker::ResizeMode resizeMode;
00076 
00077     QwtPicker::RubberBand rubberBand;
00078     QPen rubberBandPen;
00079 
00080     QwtPicker::DisplayMode trackerMode;
00081     QPen trackerPen;
00082     QFont trackerFont;
00083 
00084     QwtPolygon selection;
00085     bool isActive;
00086     QPoint labelPosition;
00087 
00088     bool mouseTracking; // used to save previous value
00089 
00090     /*
00091       On X11 the widget below the picker widgets gets paint events
00092       with a region that is the bounding rect of the mask, if it is complex.
00093       In case of (f.e) a CrossRubberBand and a text this creates complete
00094       repaints of the widget. So we better use two different widgets.
00095      */
00096      
00097 #if QT_VERSION < 0x040000
00098     QGuardedPtr<PickerWidget> rubberBandWidget;
00099     QGuardedPtr<PickerWidget> trackerWidget;
00100 #else
00101     QPointer<PickerWidget> rubberBandWidget;
00102     QPointer<PickerWidget> trackerWidget;
00103 #endif
00104 };
00105 
00106 QwtPicker::PrivateData::PickerWidget::PickerWidget(
00107         QwtPicker *picker, QWidget *parent, Type type):
00108     QWidget(parent),
00109     d_picker(picker),
00110     d_type(type)
00111 {
00112 #if QT_VERSION >= 0x040000
00113     setAttribute(Qt::WA_TransparentForMouseEvents);
00114     setAttribute(Qt::WA_NoSystemBackground);
00115     setFocusPolicy(Qt::NoFocus);
00116 #else
00117     setBackgroundMode(Qt::NoBackground);
00118     setFocusPolicy(QWidget::NoFocus);
00119     setMouseTracking(true);
00120 #endif
00121     hide();
00122 }
00123 
00124 void QwtPicker::PrivateData::PickerWidget::updateMask()
00125 {
00126     QRegion mask;
00127 
00128     if ( d_type == RubberBand )
00129     {
00130         QBitmap bm(width(), height());
00131         bm.fill(Qt::color0);
00132 
00133         QPainter painter(&bm);
00134         QPen pen = d_picker->rubberBandPen();
00135         pen.setColor(Qt::color1);
00136         painter.setPen(pen);
00137 
00138         d_picker->drawRubberBand(&painter);
00139 
00140         mask = QRegion(bm);
00141     }
00142     if ( d_type == Text )
00143     {
00144 #ifdef USE_TRACKER_RECT_MASK
00145         QBitmap bm(width(), height());
00146         QPainter painter(&bm);
00147         painter.setFont(font());
00148         mask = d_picker->trackerRect(&painter);
00149 #else
00150         QBitmap bm(width(), height());
00151         bm.fill(Qt::color0);
00152 
00153         QPainter painter(&bm);
00154         painter.setFont(font());
00155 
00156         QPen pen = d_picker->trackerPen();
00157         pen.setColor(Qt::color1);
00158         painter.setPen(pen);
00159 
00160         d_picker->drawTracker(&painter);
00161 
00162         mask = QRegion(bm);
00163 #endif
00164     }
00165 
00166 #if QT_VERSION < 0x040000
00167     QWidget *w = parentWidget();
00168     const bool doUpdate = w->isUpdatesEnabled();
00169     const Qt::BackgroundMode bgMode = w->backgroundMode();
00170     w->setUpdatesEnabled(false);
00171     if ( bgMode != Qt::NoBackground )
00172         w->setBackgroundMode(Qt::NoBackground);
00173 #endif
00174 
00175     setMask(mask);
00176 
00177 #if QT_VERSION < 0x040000
00178     if ( bgMode != Qt::NoBackground )
00179         w->setBackgroundMode(bgMode);
00180 
00181     w->setUpdatesEnabled(doUpdate);
00182 #endif
00183 
00184     setShown(!mask.isEmpty());
00185 }
00186 
00187 void QwtPicker::PrivateData::PickerWidget::paintEvent(QPaintEvent *e)
00188 {
00189     QPainter painter(this);
00190 
00191     if ( d_type == RubberBand )
00192     {
00193         painter.setClipRegion(e->region());
00194         painter.setPen(d_picker->rubberBandPen());
00195         d_picker->drawRubberBand(&painter);
00196     }
00197 
00198     if ( d_type == Text )
00199     {
00200         painter.setClipRegion(e->region());
00201 
00202         bool doDrawTracker = true;
00203 #ifndef USE_TRACKER_RECT_MASK
00204 #ifdef USE_TRACKER_BACKGROUND
00205         doDrawTracker = d_hasTrackerBackground;
00206 #else
00207         doDrawTracker = false;
00208 #endif
00209 #endif
00210 #if QT_VERSION < 0x040000
00211     if ( !doDrawTracker && QPainter::redirect(this) )
00212     {
00213         // setMask + painter redirection doesn't work
00214         doDrawTracker = true;
00215     }
00216 #endif
00217         if ( doDrawTracker )
00218         {
00219             painter.setPen(d_picker->trackerPen());
00220             d_picker->drawTracker(&painter);
00221         }
00222         else
00223             painter.fillRect(e->rect(), QBrush(d_picker->trackerPen().color()));
00224     }
00225 }
00226 
00236 QwtPicker::QwtPicker(QWidget *parent):
00237     QObject(parent)
00238 {
00239     init(parent, NoSelection, NoRubberBand, AlwaysOff);
00240 }
00241 
00251 QwtPicker::QwtPicker(int selectionFlags, RubberBand rubberBand,
00252         DisplayMode trackerMode, QWidget *parent):
00253     QObject(parent)
00254 {
00255     init(parent, selectionFlags, rubberBand, trackerMode);
00256 }
00257 
00259 QwtPicker::~QwtPicker()
00260 {
00261     setMouseTracking(false);
00262     delete d_data->stateMachine;
00263     delete d_data->rubberBandWidget;
00264     delete d_data->trackerWidget;
00265     delete d_data;
00266 }
00267 
00269 void QwtPicker::init(QWidget *parent, int selectionFlags, 
00270     RubberBand rubberBand, DisplayMode trackerMode)
00271 {
00272     d_data = new PrivateData;
00273 
00274     d_data->rubberBandWidget = NULL;
00275     d_data->trackerWidget = NULL;
00276 
00277     d_data->rubberBand = rubberBand;
00278     d_data->enabled = false;
00279     d_data->resizeMode = Stretch;
00280     d_data->trackerMode = AlwaysOff;
00281     d_data->isActive = false;
00282     d_data->labelPosition = QPoint(-1, -1);
00283     d_data->mouseTracking = false;
00284 
00285     d_data->stateMachine = NULL;
00286     setSelectionFlags(selectionFlags);
00287 
00288     if ( parent )
00289     {
00290 #if QT_VERSION >= 0x040000
00291         if ( parent->focusPolicy() == Qt::NoFocus )
00292             parent->setFocusPolicy(Qt::WheelFocus);
00293 #else
00294         if ( parent->focusPolicy() == QWidget::NoFocus )
00295             parent->setFocusPolicy(QWidget::WheelFocus);
00296 #endif
00297 
00298         d_data->trackerFont = parent->font();
00299         d_data->mouseTracking = parent->hasMouseTracking();
00300         setEnabled(true);
00301     }
00302     setTrackerMode(trackerMode);
00303 }
00304 
00308 void QwtPicker::setStateMachine(QwtPickerMachine *stateMachine)
00309 {
00310     if ( d_data->stateMachine != stateMachine )
00311     {
00312         if ( isActive() )
00313             end(false);
00314 
00315         delete d_data->stateMachine;
00316         d_data->stateMachine = stateMachine;
00317 
00318         if ( d_data->stateMachine )
00319             d_data->stateMachine->reset();
00320     }
00321 }
00322 
00339 QwtPickerMachine *QwtPicker::stateMachine(int flags) const
00340 {
00341     if ( flags & PointSelection )
00342     {
00343         if ( flags & ClickSelection )
00344             return new QwtPickerClickPointMachine;
00345         else
00346             return new QwtPickerDragPointMachine;
00347     }
00348     if ( flags & RectSelection )
00349     {
00350         if ( flags & ClickSelection )
00351             return new QwtPickerClickRectMachine;
00352         else
00353             return new QwtPickerDragRectMachine;
00354     }
00355     if ( flags & PolygonSelection )
00356     {
00357         return new QwtPickerPolygonMachine();
00358     }
00359     return NULL;
00360 }
00361 
00363 QWidget *QwtPicker::parentWidget()
00364 {
00365     QObject *obj = parent();
00366     if ( obj && obj->isWidgetType() )
00367         return (QWidget *)obj;
00368 
00369     return NULL;
00370 }
00371 
00373 const QWidget *QwtPicker::parentWidget() const
00374 {
00375     QObject *obj = parent();
00376     if ( obj && obj->isWidgetType() )
00377         return (QWidget *)obj;
00378 
00379     return NULL;
00380 }
00381 
00391 void QwtPicker::setSelectionFlags(int flags)
00392 {
00393     d_data->selectionFlags = flags;
00394     setStateMachine(stateMachine(flags));
00395 }
00396 
00402 int QwtPicker::selectionFlags() const
00403 {
00404     return d_data->selectionFlags;
00405 }
00406 
00415 void QwtPicker::setRubberBand(RubberBand rubberBand)
00416 {
00417     d_data->rubberBand = rubberBand;
00418 }
00419 
00424 QwtPicker::RubberBand QwtPicker::rubberBand() const
00425 {
00426     return d_data->rubberBand;
00427 }
00428 
00445 void QwtPicker::setTrackerMode(DisplayMode mode)
00446 {   
00447     if ( d_data->trackerMode != mode )
00448     {
00449         d_data->trackerMode = mode;
00450         setMouseTracking(d_data->trackerMode == AlwaysOn);
00451     }
00452 }   
00453 
00458 QwtPicker::DisplayMode QwtPicker::trackerMode() const
00459 {   
00460     return d_data->trackerMode;
00461 }   
00462 
00477 void QwtPicker::setResizeMode(ResizeMode mode)
00478 {
00479     d_data->resizeMode = mode;
00480 }   
00481 
00487 QwtPicker::ResizeMode QwtPicker::resizeMode() const
00488 {   
00489     return d_data->resizeMode;
00490 }
00491 
00501 void QwtPicker::setEnabled(bool enabled)
00502 {
00503     if ( d_data->enabled != enabled )
00504     {
00505         d_data->enabled = enabled;
00506 
00507         QWidget *w = parentWidget();
00508         if ( w )
00509         {
00510             if ( enabled )
00511                 w->installEventFilter(this);
00512             else
00513                 w->removeEventFilter(this);
00514         }
00515 
00516         updateDisplay();
00517     }
00518 }
00519 
00525 bool QwtPicker::isEnabled() const
00526 {
00527     return d_data->enabled;
00528 }
00529 
00536 void QwtPicker::setTrackerFont(const QFont &font)
00537 {
00538     if ( font != d_data->trackerFont )
00539     {
00540         d_data->trackerFont = font;
00541         updateDisplay();
00542     }
00543 }
00544 
00550 QFont QwtPicker::trackerFont() const
00551 {
00552     return d_data->trackerFont;
00553 }
00554 
00561 void QwtPicker::setTrackerPen(const QPen &pen)
00562 {
00563     if ( pen != d_data->trackerPen )
00564     {
00565         d_data->trackerPen = pen;
00566         updateDisplay();
00567     }
00568 }
00569 
00574 QPen QwtPicker::trackerPen() const
00575 {
00576     return d_data->trackerPen;
00577 }
00578 
00585 void QwtPicker::setRubberBandPen(const QPen &pen)
00586 {
00587     if ( pen != d_data->rubberBandPen )
00588     {
00589         d_data->rubberBandPen = pen;
00590         updateDisplay();
00591     }
00592 }
00593 
00598 QPen QwtPicker::rubberBandPen() const
00599 {
00600     return d_data->rubberBandPen;
00601 }
00602 
00616 QwtText QwtPicker::trackerText(const QPoint &pos) const
00617 {
00618     QString label;
00619 
00620     switch(rubberBand())
00621     {
00622         case HLineRubberBand:
00623             label.sprintf("%d", pos.y());
00624             break;
00625         case VLineRubberBand:
00626             label.sprintf("%d", pos.x());
00627             break;
00628         default:
00629             label.sprintf("%d, %d", pos.x(), pos.y());
00630     }
00631     return label;
00632 }
00633 
00642 void QwtPicker::drawRubberBand(QPainter *painter) const
00643 {
00644     if ( !isActive() || rubberBand() == NoRubberBand || 
00645         rubberBandPen().style() == Qt::NoPen )
00646     {
00647         return;
00648     }
00649 
00650     const QRect &pRect = pickRect();
00651     const QwtPolygon &pa = d_data->selection;
00652 
00653     if ( selectionFlags() & PointSelection )
00654     {
00655         if ( pa.count() < 1 )
00656             return;
00657 
00658         const QPoint pos = pa[0];
00659 
00660         switch(rubberBand())
00661         {
00662             case VLineRubberBand:
00663                 QwtPainter::drawLine(painter, pos.x(),
00664                     pRect.top(), pos.x(), pRect.bottom());
00665                 break;
00666 
00667             case HLineRubberBand:
00668                 QwtPainter::drawLine(painter, pRect.left(), 
00669                     pos.y(), pRect.right(), pos.y());
00670                 break;
00671 
00672             case CrossRubberBand:
00673                 QwtPainter::drawLine(painter, pos.x(),
00674                     pRect.top(), pos.x(), pRect.bottom());
00675                 QwtPainter::drawLine(painter, pRect.left(), 
00676                     pos.y(), pRect.right(), pos.y());
00677                 break;
00678             default:
00679                 break;
00680         }
00681     }
00682 
00683     else if ( selectionFlags() & RectSelection )
00684     {
00685         if ( pa.count() < 2 )
00686             return;
00687 
00688         QPoint p1 = pa[0];
00689         QPoint p2 = pa[int(pa.count() - 1)];
00690 
00691         if ( selectionFlags() & CenterToCorner )
00692         {
00693             p1.setX(p1.x() - (p2.x() - p1.x()));
00694             p1.setY(p1.y() - (p2.y() - p1.y()));
00695         }
00696         else if ( selectionFlags() & CenterToRadius )
00697         {
00698             const int radius = qwtMax(qwtAbs(p2.x() - p1.x()), 
00699                 qwtAbs(p2.y() - p1.y()));
00700             p2.setX(p1.x() + radius);
00701             p2.setY(p1.y() + radius);
00702             p1.setX(p1.x() - radius);
00703             p1.setY(p1.y() - radius);
00704         }
00705 
00706 #if QT_VERSION < 0x040000
00707         const QRect rect = QRect(p1, p2).normalize();
00708 #else
00709         const QRect rect = QRect(p1, p2).normalized();
00710 #endif
00711         switch(rubberBand())
00712         {
00713             case EllipseRubberBand:
00714                 QwtPainter::drawEllipse(painter, rect);
00715                 break;
00716             case RectRubberBand:
00717                 QwtPainter::drawRect(painter, rect);
00718                 break;
00719             default:
00720                 break;
00721         }
00722     }
00723     else if ( selectionFlags() & PolygonSelection )
00724     {
00725         if ( rubberBand() == PolygonRubberBand )
00726             painter->drawPolyline(pa);
00727     }
00728 }
00729 
00737 void QwtPicker::drawTracker(QPainter *painter) const
00738 {
00739     const QRect textRect = trackerRect(painter);
00740     if ( !textRect.isEmpty() )
00741     {
00742         QwtText label = trackerText(d_data->labelPosition);
00743         if ( !label.isEmpty() )
00744         {
00745 #ifdef USE_TRACKER_BACKGROUND
00746             if ( label.testPaintAttribute(QwtText::PaintBackground) )
00747             {
00748                 if ( d_data->trackerWidget )
00749                     d_data->trackerWidget->d_hasTrackerBackground = true;
00750                 
00751                 if ( painter->pen() != trackerPen() &&
00752                     painter->pen().color() == Qt::color1 )
00753                 {
00754                     /*
00755                       Hack time: we know, that we are painting to get the
00756                       region for the mask. The text is always inside the
00757                       textRect and on a QBitmap everything is painted in
00758                       Qt::color1. That's why we don't have to paint the text.
00759                      */
00760                     painter->fillRect(textRect, Qt::color1);
00761                     return;
00762                 }
00763             }
00764             else
00765             {
00766                 if ( d_data->trackerWidget )
00767                     d_data->trackerWidget->d_hasTrackerBackground = false;
00768             }
00769 #endif
00770 
00771 #if defined(Q_WS_MAC)
00772 #if QT_VERSION >= 0x040000 && QT_VERSION < 0x040300
00773             // Antialiased fonts are broken on the Mac.
00774             painter->save();
00775             painter->setRenderHint(QPainter::TextAntialiasing, false);
00776 #else
00777             QFont fnt = label.usedFont(painter->font());
00778             fnt.setStyleStrategy(QFont::NoAntialias);
00779             label.setFont(fnt);
00780 #endif
00781 #endif
00782             label.draw(painter, textRect);
00783 
00784 #if defined(Q_WS_MAC)
00785 #if QT_VERSION >= 0x040000 && QT_VERSION < 0x040300
00786             painter->restore();
00787 #endif
00788 #endif
00789         }
00790     }
00791 }
00792 
00793 QRect QwtPicker::trackerRect(QPainter *painter) const
00794 {
00795     if ( trackerMode() == AlwaysOff || 
00796         (trackerMode() == ActiveOnly && !isActive() ) )
00797     {
00798         return QRect();
00799     }
00800 
00801     if ( d_data->labelPosition.x() < 0 || d_data->labelPosition.y() < 0 )
00802         return QRect();
00803 
00804     QwtText text = trackerText(d_data->labelPosition);
00805     if ( text.isEmpty() )
00806         return QRect();
00807 
00808     QRect textRect(QPoint(0, 0), text.textSize(painter->font()));
00809 
00810     const QPoint &pos = d_data->labelPosition;
00811 
00812     int alignment = 0;
00813     if ( isActive() && d_data->selection.count() > 1 
00814         && rubberBand() != NoRubberBand )
00815     {
00816         const QPoint last = 
00817             d_data->selection[int(d_data->selection.count()) - 2];
00818 
00819         alignment |= (pos.x() >= last.x()) ? Qt::AlignRight : Qt::AlignLeft;
00820         alignment |= (pos.y() > last.y()) ? Qt::AlignBottom : Qt::AlignTop;
00821     }
00822     else
00823         alignment = Qt::AlignTop | Qt::AlignRight;
00824 
00825     const int margin = 5;
00826 
00827     int x = pos.x();
00828     if ( alignment & Qt::AlignLeft )
00829         x -= textRect.width() + margin;
00830     else if ( alignment & Qt::AlignRight )
00831         x += margin;
00832 
00833     int y = pos.y();
00834     if ( alignment & Qt::AlignBottom )
00835         y += margin;
00836     else if ( alignment & Qt::AlignTop )
00837         y -= textRect.height() + margin;
00838     
00839     textRect.moveTopLeft(QPoint(x, y));
00840 
00841     int right = qwtMin(textRect.right(), pickRect().right() - margin);
00842     int bottom = qwtMin(textRect.bottom(), pickRect().bottom() - margin);
00843     textRect.moveBottomRight(QPoint(right, bottom));
00844 
00845     int left = qwtMax(textRect.left(), pickRect().left() + margin);
00846     int top = qwtMax(textRect.top(), pickRect().top() + margin);
00847     textRect.moveTopLeft(QPoint(left, top));
00848 
00849     return textRect;
00850 }
00851 
00864 bool QwtPicker::eventFilter(QObject *o, QEvent *e)
00865 {
00866     if ( o && o == parentWidget() )
00867     {
00868         switch(e->type())
00869         {
00870             case QEvent::Resize:
00871             {
00872                 const QResizeEvent *re = (QResizeEvent *)e;
00873                 if ( d_data->resizeMode == Stretch )
00874                     stretchSelection(re->oldSize(), re->size());
00875 
00876                 if ( d_data->rubberBandWidget )
00877                     d_data->rubberBandWidget->resize(re->size());
00878              
00879                 if ( d_data->trackerWidget )
00880                     d_data->trackerWidget->resize(re->size());
00881                 break;
00882             }
00883             case QEvent::Leave:
00884                 widgetLeaveEvent(e);
00885                 break;
00886             case QEvent::MouseButtonPress:
00887                 widgetMousePressEvent((QMouseEvent *)e);
00888                 break;
00889             case QEvent::MouseButtonRelease:
00890                 widgetMouseReleaseEvent((QMouseEvent *)e);
00891                 break;
00892             case QEvent::MouseButtonDblClick:
00893                 widgetMouseDoubleClickEvent((QMouseEvent *)e);
00894                 break;
00895             case QEvent::MouseMove:
00896                 widgetMouseMoveEvent((QMouseEvent *)e);
00897                 break;
00898             case QEvent::KeyPress:
00899                 widgetKeyPressEvent((QKeyEvent *)e);
00900                 break;
00901             case QEvent::KeyRelease:
00902                 widgetKeyReleaseEvent((QKeyEvent *)e);
00903                 break;
00904             case QEvent::Wheel:
00905                 widgetWheelEvent((QWheelEvent *)e);
00906                 break;
00907             default:
00908                 break;
00909         }
00910     }
00911     return false;
00912 }
00913 
00924 void QwtPicker::widgetMousePressEvent(QMouseEvent *e)
00925 {
00926     transition(e);
00927 }
00928 
00938 void QwtPicker::widgetMouseMoveEvent(QMouseEvent *e)
00939 {
00940     if ( pickRect().contains(e->pos()) )
00941         d_data->labelPosition = e->pos();
00942     else
00943         d_data->labelPosition = QPoint(-1, -1);
00944 
00945     if ( !isActive() )
00946         updateDisplay();
00947 
00948     transition(e);
00949 }
00950 
00958 void QwtPicker::widgetLeaveEvent(QEvent *)   
00959 {
00960     d_data->labelPosition = QPoint(-1, -1);
00961     if ( !isActive() )
00962         updateDisplay();
00963 }
00964 
00975 void QwtPicker::widgetMouseReleaseEvent(QMouseEvent *e)
00976 {
00977     transition(e);
00978 }
00979 
00989 void QwtPicker::widgetMouseDoubleClickEvent(QMouseEvent *me)
00990 {
00991     transition(me);
00992 }
00993     
00994 
01004 void QwtPicker::widgetWheelEvent(QWheelEvent *e)
01005 {
01006     if ( pickRect().contains(e->pos()) )
01007         d_data->labelPosition = e->pos();
01008     else
01009         d_data->labelPosition = QPoint(-1, -1);
01010 
01011     updateDisplay();
01012 
01013     transition(e);
01014 }
01015 
01029 void QwtPicker::widgetKeyPressEvent(QKeyEvent *ke)
01030 {
01031     int dx = 0;
01032     int dy = 0;
01033 
01034     int offset = 1;
01035     if ( ke->isAutoRepeat() )
01036         offset = 5;
01037 
01038     if ( keyMatch(KeyLeft, ke) )
01039         dx = -offset;
01040     else if ( keyMatch(KeyRight, ke) )
01041         dx = offset;
01042     else if ( keyMatch(KeyUp, ke) )
01043         dy = -offset;
01044     else if ( keyMatch(KeyDown, ke) )
01045         dy = offset;
01046     else if ( keyMatch(KeyAbort, ke) )
01047     {
01048         if ( d_data->stateMachine )
01049             d_data->stateMachine->reset();
01050 
01051         if (isActive())
01052             end(false);
01053     }
01054     else
01055         transition(ke);
01056 
01057     if ( dx != 0 || dy != 0 )
01058     {
01059         const QRect rect = pickRect();
01060         const QPoint pos = parentWidget()->mapFromGlobal(QCursor::pos());
01061 
01062         int x = pos.x() + dx;
01063         x = qwtMax(rect.left(), x);
01064         x = qwtMin(rect.right(), x);
01065 
01066         int y = pos.y() + dy;
01067         y = qwtMax(rect.top(), y);
01068         y = qwtMin(rect.bottom(), y);
01069 
01070         QCursor::setPos(parentWidget()->mapToGlobal(QPoint(x, y)));
01071     }
01072 }
01073  
01083 void QwtPicker::widgetKeyReleaseEvent(QKeyEvent *ke)
01084 {
01085     transition(ke);
01086 }
01087 
01095 void QwtPicker::transition(const QEvent *e)
01096 {
01097     if ( !d_data->stateMachine )
01098         return;
01099 
01100     QwtPickerMachine::CommandList commandList =
01101         d_data->stateMachine->transition(*this, e);
01102 
01103     QPoint pos;
01104     switch(e->type())
01105     {
01106         case QEvent::MouseButtonDblClick:
01107         case QEvent::MouseButtonPress:
01108         case QEvent::MouseButtonRelease:
01109         case QEvent::MouseMove:
01110         {
01111             const QMouseEvent *me = (QMouseEvent *)e;
01112             pos = me->pos();
01113             break;
01114         }
01115         default:
01116             pos = parentWidget()->mapFromGlobal(QCursor::pos());
01117     }
01118 
01119     for ( uint i = 0; i < (uint)commandList.count(); i++ )
01120     {
01121         switch(commandList[i])
01122         {
01123             case QwtPickerMachine::Begin:
01124             {
01125                 begin();
01126                 break;
01127             }
01128             case QwtPickerMachine::Append:
01129             {
01130                 append(pos);
01131                 break;
01132             }
01133             case QwtPickerMachine::Move:
01134             {
01135                 move(pos);
01136                 break;
01137             }
01138             case QwtPickerMachine::End:
01139             {
01140                 end();
01141                 break;
01142             }
01143         }
01144     }
01145 }
01146 
01152 void QwtPicker::begin()
01153 {
01154     if ( d_data->isActive )
01155         return;
01156 
01157     d_data->selection.resize(0);
01158     d_data->isActive = true;
01159 
01160     if ( trackerMode() != AlwaysOff )
01161     {
01162         if ( d_data->labelPosition.x() < 0 || d_data->labelPosition.y() < 0 ) 
01163         {
01164             QWidget *w = parentWidget();
01165             if ( w )
01166                 d_data->labelPosition = w->mapFromGlobal(QCursor::pos());
01167         }
01168     }
01169 
01170     updateDisplay();
01171     setMouseTracking(true);
01172 }
01173 
01184 bool QwtPicker::end(bool ok)
01185 {
01186     if ( d_data->isActive )
01187     {
01188         setMouseTracking(false);
01189 
01190         d_data->isActive = false;
01191 
01192         if ( trackerMode() == ActiveOnly )
01193             d_data->labelPosition = QPoint(-1, -1);
01194 
01195         if ( ok )
01196             ok = accept(d_data->selection);
01197 
01198         if ( ok )
01199             emit selected(d_data->selection);
01200         else
01201             d_data->selection.resize(0);
01202 
01203         updateDisplay();
01204     }
01205     else
01206         ok = false;
01207 
01208     return ok;
01209 }
01210 
01219 void QwtPicker::append(const QPoint &pos)
01220 {
01221     if ( d_data->isActive )
01222     {
01223         const int idx = d_data->selection.count();
01224         d_data->selection.resize(idx + 1);
01225         d_data->selection[idx] = pos;
01226 
01227         updateDisplay();
01228 
01229         emit appended(pos);
01230     }
01231 }
01232 
01241 void QwtPicker::move(const QPoint &pos)
01242 {
01243     if ( d_data->isActive )
01244     {
01245         const int idx = d_data->selection.count() - 1;
01246         if ( idx >= 0 )
01247         {
01248             if ( d_data->selection[idx] != pos )
01249             {
01250                 d_data->selection[idx] = pos;
01251 
01252                 updateDisplay();
01253 
01254                 emit moved(pos);
01255             }
01256         }
01257     }
01258 }
01259 
01260 bool QwtPicker::accept(QwtPolygon &) const
01261 {
01262     return true;
01263 }
01264 
01269 bool QwtPicker::isActive() const 
01270 {
01271     return d_data->isActive;
01272 }
01273 
01275 const QwtPolygon &QwtPicker::selection() const
01276 {
01277     return d_data->selection;
01278 }
01279 
01289 void QwtPicker::stretchSelection(const QSize &oldSize, const QSize &newSize)
01290 {
01291     const double xRatio =
01292         double(newSize.width()) / double(oldSize.width());
01293     const double yRatio =
01294         double(newSize.height()) / double(oldSize.height());
01295 
01296     for ( int i = 0; i < int(d_data->selection.count()); i++ )
01297     {
01298         QPoint &p = d_data->selection[i];
01299         p.setX(qRound(p.x() * xRatio));
01300         p.setY(qRound(p.y() * yRatio));
01301 
01302         emit changed(d_data->selection);
01303     }
01304 }
01305 
01319 void QwtPicker::setMouseTracking(bool enable)
01320 {
01321     QWidget *widget = parentWidget();
01322     if ( !widget )
01323         return;
01324 
01325     if ( enable )
01326     {
01327         d_data->mouseTracking = widget->hasMouseTracking();
01328         widget->setMouseTracking(true);
01329     }
01330     else
01331     {
01332         widget->setMouseTracking(d_data->mouseTracking);
01333     }
01334 }
01335 
01341 QRect QwtPicker::pickRect() const
01342 {
01343     QRect rect;
01344 
01345     const QWidget *widget = parentWidget();
01346     if ( !widget )
01347         return rect;
01348 
01349     if ( widget->inherits("QFrame") )
01350         rect = ((QFrame *)widget)->contentsRect();
01351     else
01352         rect = widget->rect();
01353 
01354     return rect;
01355 }
01356 
01357 void QwtPicker::updateDisplay()
01358 {
01359     QWidget *w = parentWidget();
01360 
01361     bool showRubberband = false;
01362     bool showTracker = false;
01363     if ( w && w->isVisible() && d_data->enabled )
01364     {
01365         if ( rubberBand() != NoRubberBand && isActive() &&
01366             rubberBandPen().style() != Qt::NoPen )
01367         {
01368             showRubberband = true;
01369         }
01370 
01371         if ( trackerMode() == AlwaysOn ||
01372             (trackerMode() == ActiveOnly && isActive() ) )
01373         {
01374             if ( trackerPen() != Qt::NoPen )
01375                 showTracker = true;
01376         }
01377     }
01378 
01379 #if QT_VERSION < 0x040000
01380     QGuardedPtr<PrivateData::PickerWidget> &rw = d_data->rubberBandWidget;
01381 #else
01382     QPointer<PrivateData::PickerWidget> &rw = d_data->rubberBandWidget;
01383 #endif
01384     if ( showRubberband )
01385     {
01386         if ( rw.isNull() )
01387         {
01388             rw = new PrivateData::PickerWidget(
01389                 this, w, PrivateData::PickerWidget::RubberBand);
01390             rw->resize(w->size());
01391         }
01392         rw->updateMask();
01393         rw->update(); // Needed, when the mask doesn't change
01394     }
01395     else
01396         delete rw;
01397 
01398 #if QT_VERSION < 0x040000
01399     QGuardedPtr<PrivateData::PickerWidget> &tw = d_data->trackerWidget;
01400 #else
01401     QPointer<PrivateData::PickerWidget> &tw = d_data->trackerWidget;
01402 #endif
01403     if ( showTracker )
01404     {
01405         if ( tw.isNull() )
01406         {
01407             tw = new PrivateData::PickerWidget(
01408                 this, w, PrivateData::PickerWidget::Text);
01409             tw->resize(w->size());
01410         }
01411         tw->updateMask();
01412         tw->update(); // Needed, when the mask doesn't change
01413     }
01414     else
01415         delete tw;
01416 }
01417 
01418 const QWidget *QwtPicker::rubberBandWidget() const
01419 {
01420     return d_data->rubberBandWidget;
01421 }
01422 
01423 const QWidget *QwtPicker::trackerWidget() const
01424 {
01425     return d_data->trackerWidget;
01426 }
01427 

Generated on Mon Jun 11 07:41:38 2007 for Qwt User's Guide by  doxygen 1.4.6