00001
00002
00003
00004
00005
00006
00007
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
00029
00030
00031
00032
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
00058
00059
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;
00089
00090
00091
00092
00093
00094
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
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
00756
00757
00758
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
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();
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();
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