10#include "qwt_picker.h"
11#include "qwt_picker_machine.h"
12#include "qwt_painter.h"
14#include "qwt_widget_overlay.h"
19#include <qpainterpath.h>
24static inline QRegion qwtMaskRegion(
const QRect& r,
int penWidth )
26 const int pw = qMax( penWidth, 1 );
27 const int pw2 = penWidth / 2;
29 int x1 = r.left() - pw2;
30 int x2 = r.right() + 1 + pw2 + ( pw % 2 );
32 int y1 = r.top() - pw2;
33 int y2 = r.bottom() + 1 + pw2 + ( pw % 2 );
37 region += QRect( x1, y1, x2 - x1, pw );
38 region += QRect( x1, y1, pw, y2 - y1 );
39 region += QRect( x1, y2 - pw, x2 - x1, pw );
40 region += QRect( x2 - pw, y1, pw, y2 - y1 );
45static inline QRegion qwtMaskRegion(
const QLine& l,
int penWidth )
47 const int pw = qMax( penWidth, 1 );
48 const int pw2 = penWidth / 2;
52 if ( l.x1() == l.x2() )
54 region += QRect( l.x1() - pw2, l.y1(),
55 pw, l.y2() ).normalized();
57 else if ( l.y1() == l.y2() )
59 region += QRect( l.x1(), l.y1() - pw2,
60 l.x2(), pw ).normalized();
71 Rubberband(
QwtPicker* picker, QWidget* parent )
79 virtual void drawOverlay( QPainter* painter )
const QWT_OVERRIDE
81 painter->setPen( m_picker->rubberBandPen() );
82 m_picker->drawRubberBand( painter );
85 virtual QRegion maskHint() const QWT_OVERRIDE
87 return m_picker->rubberBandMask();
96 Tracker(
QwtPicker* picker, QWidget* parent )
104 virtual void drawOverlay( QPainter* painter )
const QWT_OVERRIDE
106 painter->setPen( m_picker->trackerPen() );
107 m_picker->drawTracker( painter );
110 virtual QRegion maskHint() const QWT_OVERRIDE
112 return m_picker->trackerMask();
119class QwtPicker::PrivateData
124 stateMachine( NULL ),
129 trackerPosition( -1, -1 ),
130 mouseTracking( false ),
148 QPolygon pickedPoints;
150 QPoint trackerPosition;
154 QPointer< Rubberband > rubberBandOverlay;
155 QPointer< Tracker > trackerOverlay;
192 setMouseTracking(
false );
194 delete m_data->stateMachine;
195 delete m_data->rubberBandOverlay;
196 delete m_data->trackerOverlay;
202void QwtPicker::init( QWidget* parent,
203 RubberBand rubberBand, DisplayMode trackerMode )
205 m_data =
new PrivateData;
211 if ( parent->focusPolicy() == Qt::NoFocus )
212 parent->setFocusPolicy( Qt::WheelFocus );
214 m_data->openGL = parent->inherits(
"QGLWidget" );
215 m_data->trackerFont = parent->font();
216 m_data->mouseTracking = parent->hasMouseTracking();
236 delete m_data->stateMachine;
239 if ( m_data->stateMachine )
240 m_data->stateMachine->
reset();
250 return m_data->stateMachine;
259 return m_data->stateMachine;
265 QObject* obj = parent();
266 if ( obj && obj->isWidgetType() )
267 return static_cast< QWidget*
>( obj );
275 QObject* obj = parent();
276 if ( obj && obj->isWidgetType() )
277 return static_cast< const QWidget*
>( obj );
301 return m_data->rubberBand;
322 if ( m_data->trackerMode != mode )
324 m_data->trackerMode = mode;
325 setMouseTracking( m_data->trackerMode ==
AlwaysOn );
335 return m_data->trackerMode;
354 m_data->resizeMode = mode;
364 return m_data->resizeMode;
378 if ( m_data->enabled != enabled )
380 m_data->enabled = enabled;
386 w->installEventFilter(
this );
388 w->removeEventFilter(
this );
402 return m_data->enabled;
413 if ( font != m_data->trackerFont )
415 m_data->trackerFont = font;
427 return m_data->trackerFont;
438 if ( pen != m_data->trackerPen )
440 m_data->trackerPen = pen;
451 return m_data->trackerPen;
462 if ( pen != m_data->rubberBandPen )
464 m_data->rubberBandPen = pen;
475 return m_data->rubberBandPen;
498 label = QString::number( pos.y() );
501 label = QString::number( pos.x() );
504 label = QString::number( pos.x() ) +
", " + QString::number( pos.y() );
541 if ( m_data->stateMachine )
547 switch ( selectionType )
552 if ( pa.count() < 1 )
555 const QPoint pos = pa[0];
557 const QRect pRect =
pickArea().boundingRect().toRect();
562 mask += qwtMaskRegion( QLine( pos.x(), pRect.top(),
563 pos.x(), pRect.bottom() ), pw );
568 mask += qwtMaskRegion( QLine( pRect.left(), pos.y(),
569 pRect.right(), pos.y() ), pw );
574 mask += qwtMaskRegion( QLine( pos.x(), pRect.top(),
575 pos.x(), pRect.bottom() ), pw );
576 mask += qwtMaskRegion( QLine( pRect.left(), pos.y(),
577 pRect.right(), pos.y() ), pw );
587 if ( pa.count() < 2 )
594 const QRect r = QRect( pa.first(), pa.last() );
595 mask = qwtMaskRegion( r.normalized(), pw );
600 const QRect r = QRect( pa.first(), pa.last() );
601 mask += r.adjusted( -pw, -pw, pw, pw );
616 const int off = 2 * pw;
617 const QRect r = pa.boundingRect();
618 mask += r.adjusted( -off, -off, off, off );
650 if ( m_data->stateMachine )
653 switch ( selectionType )
658 if ( pa.count() < 1 )
661 const QPoint pos = pa[0];
663 const QRect pRect =
pickArea().boundingRect().toRect();
669 pRect.top(), pos.x(), pRect.bottom() );
675 pos.y(), pRect.right(), pos.y() );
681 pRect.top(), pos.x(), pRect.bottom() );
683 pos.y(), pRect.right(), pos.y() );
693 if ( pa.count() < 2 )
696 const QRect rect = QRect( pa.first(), pa.last() ).normalized();
717 painter->drawPolyline( pa );
734 const QRect textRect =
trackerRect( painter->font() );
735 if ( !textRect.isEmpty() )
739 label.
draw( painter, textRect );
800 return m_data->trackerPosition;
820 if ( m_data->trackerPosition.x() < 0 || m_data->trackerPosition.y() < 0 )
827 const QSizeF textSize = text.
textSize( font );
829 const int w = qwtCeil( textSize.width() );
830 const int h = qwtCeil( textSize.height() );
846 const QPoint& pos = m_data->trackerPosition;
847 QRect infoRect( 0, 0, size.width(), size.height() );
850 if (
isActive() && m_data->pickedPoints.count() > 1
854 m_data->pickedPoints[ m_data->pickedPoints.count() - 2 ];
856 alignment |= ( pos.x() >= last.x() ) ? Qt::AlignRight : Qt::AlignLeft;
857 alignment |= ( pos.y() > last.y() ) ? Qt::AlignBottom : Qt::AlignTop;
861 alignment = Qt::AlignTop | Qt::AlignRight;
864 const int margin = 5;
867 if ( alignment & Qt::AlignLeft )
868 x -= infoRect.width() + margin;
869 else if ( alignment & Qt::AlignRight )
873 if ( alignment & Qt::AlignBottom )
875 else if ( alignment & Qt::AlignTop )
876 y -= infoRect.height() + margin;
878 infoRect.moveTopLeft( QPoint( x, y ) );
880 const QRect pickRect =
pickArea().boundingRect().toRect();
882 int right = qMin( infoRect.right(), pickRect.right() - margin );
883 int bottom = qMin( infoRect.bottom(), pickRect.bottom() - margin );
884 infoRect.moveBottomRight( QPoint( right, bottom ) );
886 int left = qMax( infoRect.left(), pickRect.left() + margin );
887 int top = qMax( infoRect.top(), pickRect.top() + margin );
888 infoRect.moveTopLeft( QPoint( left, top ) );
916 switch ( event->type() )
920 const QResizeEvent* re =
static_cast< QResizeEvent*
>( event );
928 if ( m_data->trackerOverlay )
929 m_data->trackerOverlay->resize( re->size() );
931 if ( m_data->rubberBandOverlay )
932 m_data->rubberBandOverlay->resize( re->size() );
934 if ( m_data->resizeMode ==
Stretch )
950 case QEvent::MouseButtonPress:
955 case QEvent::MouseButtonRelease:
960 case QEvent::MouseButtonDblClick:
965 case QEvent::MouseMove:
970 case QEvent::KeyPress:
975 case QEvent::KeyRelease:
1017 if (
pickArea().contains( mouseEvent->pos() ) )
1018 m_data->trackerPosition = mouseEvent->pos();
1020 m_data->trackerPosition = QPoint( -1, -1 );
1055 m_data->trackerPosition = QPoint( -1, -1 );
1102#if QT_VERSION < 0x050e00
1103 const QPoint wheelPos = wheelEvent->pos();
1105 const QPoint wheelPos = wheelEvent->position().toPoint();
1107 if (
pickArea().contains( wheelPos ) )
1108 m_data->trackerPosition = wheelPos;
1110 m_data->trackerPosition = QPoint( -1, -1 );
1137 if ( keyEvent->isAutoRepeat() )
1155 if ( dx != 0 || dy != 0 )
1157 const QRect rect =
pickArea().boundingRect().toRect();
1158 const QPoint pos =
parentWidget()->mapFromGlobal( QCursor::pos() );
1160 int x = pos.x() + dx;
1161 x = qMax( rect.left(), x );
1162 x = qMin( rect.right(), x );
1164 int y = pos.y() + dy;
1165 y = qMax( rect.top(), y );
1166 y = qMin( rect.bottom(), y );
1168 QCursor::setPos(
parentWidget()->mapToGlobal( QPoint( x, y ) ) );
1197 if ( !m_data->stateMachine )
1201 m_data->stateMachine->
transition( *
this, event );
1204 switch ( event->type() )
1206 case QEvent::MouseButtonDblClick:
1207 case QEvent::MouseButtonPress:
1208 case QEvent::MouseButtonRelease:
1209 case QEvent::MouseMove:
1211 const QMouseEvent* me =
1212 static_cast< const QMouseEvent*
>( event );
1220 for (
int i = 0; i < commandList.count(); i++ )
1222 switch ( commandList[i] )
1224 case QwtPickerMachine::Begin:
1229 case QwtPickerMachine::Append:
1234 case QwtPickerMachine::Move:
1239 case QwtPickerMachine::Remove:
1244 case QwtPickerMachine::End:
1260 if ( m_data->isActive )
1263 m_data->pickedPoints.clear();
1264 m_data->isActive =
true;
1269 if ( m_data->trackerPosition.x() < 0 || m_data->trackerPosition.y() < 0 )
1273 m_data->trackerPosition = w->mapFromGlobal( QCursor::pos() );
1278 setMouseTracking(
true );
1293 if ( m_data->isActive )
1295 setMouseTracking(
false );
1297 m_data->isActive =
false;
1301 m_data->trackerPosition = QPoint( -1, -1 );
1304 ok =
accept( m_data->pickedPoints );
1307 Q_EMIT
selected( m_data->pickedPoints );
1309 m_data->pickedPoints.clear();
1324 if ( m_data->stateMachine )
1325 m_data->stateMachine->
reset();
1341 if ( m_data->isActive )
1343 m_data->pickedPoints += pos;
1359 if ( m_data->isActive && !m_data->pickedPoints.isEmpty() )
1361 QPoint& point = m_data->pickedPoints.last();
1367 Q_EMIT
moved( pos );
1380 if ( m_data->isActive && !m_data->pickedPoints.isEmpty() )
1382#if QT_VERSION >= 0x050100
1383 const QPoint pos = m_data->pickedPoints.takeLast();
1385 const QPoint pos = m_data->pickedPoints.last();
1386 m_data->pickedPoints.resize( m_data->pickedPoints.count() - 1 );
1414 return m_data->isActive;
1424 return m_data->pickedPoints;
1438 if ( oldSize.isEmpty() )
1445 const double xRatio = double( newSize.width() ) / double( oldSize.width() );
1446 const double yRatio = double( newSize.height() ) / double( oldSize.height() );
1448 for (
int i = 0; i < m_data->pickedPoints.count(); i++ )
1450 QPoint& p = m_data->pickedPoints[i];
1451 p.setX( qRound( p.x() * xRatio ) );
1452 p.setY( qRound( p.y() * yRatio ) );
1454 Q_EMIT
changed( m_data->pickedPoints );
1471void QwtPicker::setMouseTracking(
bool enable )
1479 m_data->mouseTracking = widget->hasMouseTracking();
1480 widget->setMouseTracking(
true );
1484 widget->setMouseTracking( m_data->mouseTracking );
1499 path.addRect( widget->contentsRect() );
1509 bool showRubberband =
false;
1510 bool showTracker =
false;
1512 if ( w && w->isVisible() && m_data->enabled )
1517 showRubberband =
true;
1531 QPointer< Rubberband >& rw = m_data->rubberBandOverlay;
1532 if ( showRubberband )
1536 rw =
new Rubberband(
this, NULL );
1537 rw->setObjectName(
"PickerRubberBand" );
1539 rw->resize( w->size() );
1547 rw->updateOverlay();
1551 if ( m_data->openGL )
1567 QPointer< Tracker >& tw = m_data->trackerOverlay;
1572 tw =
new Tracker(
this, NULL );
1573 tw->setObjectName(
"PickerTracker" );
1575 tw->resize( w->size() );
1577 tw->setFont( m_data->trackerFont );
1578 tw->updateOverlay();
1582 if ( m_data->openGL )
1602 return m_data->rubberBandOverlay;
1608 return m_data->trackerOverlay;
1611#include "moc_qwt_picker.cpp"
bool keyMatch(KeyPatternCode, const QKeyEvent *) const
Compare a key event with an event pattern.
@ KeyAbort
Qt::Key_Escape.
static void drawEllipse(QPainter *, const QRectF &)
Wrapper for QPainter::drawEllipse()
static void drawRect(QPainter *, qreal x, qreal y, qreal w, qreal h)
Wrapper for QPainter::drawRect()
static qreal devicePixelRatio(const QPaintDevice *)
static void drawLine(QPainter *, qreal x1, qreal y1, qreal x2, qreal y2)
Wrapper for QPainter::drawLine()
QwtPicker provides selections on a widget.
@ AlwaysOn
Display always.
@ AlwaysOff
Display never.
@ ActiveOnly
Display only when the selection is active.
virtual void updateDisplay()
Update the state of rubber band and tracker label.
QFont trackerFont() const
ResizeMode resizeMode() const
virtual void drawRubberBand(QPainter *) const
RubberBand rubberBand() const
void setRubberBandPen(const QPen &)
virtual QRegion trackerMask() const
virtual void stretchSelection(const QSize &oldSize, const QSize &newSize)
virtual bool eventFilter(QObject *, QEvent *) override
Event filter.
void selected(const QPolygon &polygon)
QPen rubberBandPen() const
const QwtWidgetOverlay * rubberBandOverlay() const
virtual void widgetMousePressEvent(QMouseEvent *)
virtual void move(const QPoint &)
virtual ~QwtPicker()
Destructor.
virtual void append(const QPoint &)
void setStateMachine(QwtPickerMachine *)
virtual void drawTracker(QPainter *) const
virtual QRegion rubberBandMask() const
QPoint trackerPosition() const
virtual void widgetEnterEvent(QEvent *)
void setRubberBand(RubberBand)
const QwtWidgetOverlay * trackerOverlay() const
virtual void widgetMouseMoveEvent(QMouseEvent *)
virtual void widgetLeaveEvent(QEvent *)
virtual void transition(const QEvent *)
virtual bool accept(QPolygon &) const
Validate and fix up the selection.
void setTrackerMode(DisplayMode)
Set the display mode of the tracker.
virtual QPainterPath pickArea() const
virtual void widgetKeyReleaseEvent(QKeyEvent *)
void setTrackerFont(const QFont &)
void setEnabled(bool)
En/disable the picker.
DisplayMode trackerMode() const
virtual QPolygon adjustedPoints(const QPolygon &) const
Map the pickedPoints() into a selection()
@ VLineRubberBand
A vertical line ( only for QwtPickerMachine::PointSelection )
@ CrossRubberBand
A crosshair ( only for QwtPickerMachine::PointSelection )
@ EllipseRubberBand
An ellipse ( only for QwtPickerMachine::RectSelection )
@ PolygonRubberBand
A polygon ( only for QwtPickerMachine::PolygonSelection )
@ HLineRubberBand
A horizontal line ( only for QwtPickerMachine::PointSelection )
@ NoRubberBand
No rubberband.
@ RectRubberBand
A rectangle ( only for QwtPickerMachine::RectSelection )
@ Stretch
All points are scaled according to the new size,.
virtual QwtText trackerText(const QPoint &pos) const
Return the label for a position.
virtual void widgetMouseReleaseEvent(QMouseEvent *)
virtual bool end(bool ok=true)
Close a selection setting the state to inactive.
void appended(const QPoint &pos)
QWidget * parentWidget()
Return the parent widget, where the selection happens.
void moved(const QPoint &pos)
const QPolygon & pickedPoints() const
const QwtPickerMachine * stateMachine() const
void removed(const QPoint &pos)
void changed(const QPolygon &selection)
virtual QRect trackerRect(const QFont &) const
virtual void widgetMouseDoubleClickEvent(QMouseEvent *)
virtual void widgetKeyPressEvent(QKeyEvent *)
void setTrackerPen(const QPen &)
void setResizeMode(ResizeMode)
Set the resize mode.
virtual void widgetWheelEvent(QWheelEvent *)
QwtPicker(QWidget *parent)
QPolygon selection() const
A state machine for QwtPicker selections.
@ NoSelection
The state machine not usable for any type of selection.
@ RectSelection
The state machine is for selecting a rectangle (2 points).
@ PolygonSelection
The state machine is for selecting a polygon (many points).
@ PointSelection
The state machine is for selecting a single point.
SelectionType selectionType() const
Return the selection type.
virtual QList< Command > transition(const QwtEventPattern &, const QEvent *)=0
Transition.
void reset()
Set the current state to 0.
A class representing a text.
void draw(QPainter *painter, const QRectF &rect) const