1
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
3
* Copyright (C) 1997 Josef Wilgen
4
* Copyright (C) 2002 Uwe Rathmann
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the Qwt License, Version 1.0
8
*****************************************************************************/
10
#include "qwt_panner.h"
11
#include "qwt_picker.h"
18
static QVector<QwtPicker *> qwtActivePickers( QWidget *w )
20
QVector<QwtPicker *> pickers;
22
QObjectList children = w->children();
23
for ( int i = 0; i < children.size(); i++ )
25
QObject *obj = children[i];
26
if ( obj->inherits( "QwtPicker" ) )
28
QwtPicker *picker = ( QwtPicker * )obj;
29
if ( picker->isEnabled() )
37
class QwtPanner::PrivateData
41
button( Qt::LeftButton ),
42
buttonState( Qt::NoButton ),
43
abortKey( Qt::Key_Escape ),
44
abortKeyState( Qt::NoButton ),
47
restoreCursor( NULL ),
52
orientations = Qt::Vertical | Qt::Horizontal;
76
QCursor *restoreCursor;
80
Qt::Orientations orientations;
84
Creates an panner that is enabled for the left mouse button.
86
\param parent Parent widget to be panned
88
QwtPanner::QwtPanner( QWidget *parent ):
91
d_data = new PrivateData();
93
setAttribute( Qt::WA_TransparentForMouseEvents );
94
setAttribute( Qt::WA_NoSystemBackground );
95
setFocusPolicy( Qt::NoFocus );
102
QwtPanner::~QwtPanner()
108
Change the mouse button
109
The defaults are Qt::LeftButton and Qt::NoButton
111
void QwtPanner::setMouseButton( int button, int buttonState )
113
d_data->button = button;
114
d_data->buttonState = buttonState;
117
//! Get the mouse button
118
void QwtPanner::getMouseButton( int &button, int &buttonState ) const
120
button = d_data->button;
121
buttonState = d_data->buttonState;
126
The defaults are Qt::Key_Escape and Qt::NoButton
128
\param key Key ( See Qt::Keycode )
131
void QwtPanner::setAbortKey( int key, int state )
133
d_data->abortKey = key;
134
d_data->abortKeyState = state;
137
//! Get the abort key
138
void QwtPanner::getAbortKey( int &key, int &state ) const
140
key = d_data->abortKey;
141
state = d_data->abortKeyState;
145
Change the cursor, that is active while panning
146
The default is the cursor of the parent widget.
148
\param cursor New cursor
153
void QwtPanner::setCursor( const QCursor &cursor )
155
d_data->cursor = new QCursor( cursor );
160
\return Cursor that is active while panning
164
const QCursor QwtPanner::cursor() const
166
if ( d_data->cursor )
167
return *d_data->cursor;
169
if ( parentWidget() )
170
return parentWidget()->cursor();
177
\brief En/disable the panner
179
When enabled is true an event filter is installed for
180
the observed widget, otherwise the event filter is removed.
182
\param on true or false
183
\sa isEnabled(), eventFilter()
185
void QwtPanner::setEnabled( bool on )
187
if ( d_data->isEnabled != on )
189
d_data->isEnabled = on;
191
QWidget *w = parentWidget();
194
if ( d_data->isEnabled )
196
w->installEventFilter( this );
200
w->removeEventFilter( this );
208
Set the orientations, where panning is enabled
209
The default value is in both directions: Qt::Horizontal | Qt::Vertical
213
void QwtPanner::setOrientations( Qt::Orientations o )
215
d_data->orientations = o;
218
//! Return the orientation, where paning is enabled
219
Qt::Orientations QwtPanner::orientations() const
221
return d_data->orientations;
225
Return true if a orientatio is enabled
226
\sa orientations(), setOrientations()
228
bool QwtPanner::isOrientationEnabled( Qt::Orientation o ) const
230
return d_data->orientations & o;
234
\return true when enabled, false otherwise
235
\sa setEnabled, eventFilter()
237
bool QwtPanner::isEnabled() const
239
return d_data->isEnabled;
245
Repaint the grabbed pixmap on its current position and
246
fill the empty spaces by the background of the parent widget.
248
\param pe Paint event
250
void QwtPanner::paintEvent( QPaintEvent *pe )
252
int dx = d_data->pos.x() - d_data->initialPos.x();
253
int dy = d_data->pos.y() - d_data->initialPos.y();
255
QRect r( 0, 0, d_data->pixmap.width(), d_data->pixmap.height() );
256
r.moveCenter( QPoint( r.center().x() + dx, r.center().y() + dy ) );
258
QPixmap pm( size() );
259
pm.fill( parentWidget(), 0, 0 );
261
QPainter painter( &pm );
263
if ( !d_data->contentsMask.isNull() )
265
QPixmap masked = d_data->pixmap;
266
masked.setMask( d_data->contentsMask );
267
painter.drawPixmap( r, masked );
271
painter.drawPixmap( r, d_data->pixmap );
276
if ( !d_data->contentsMask.isNull() )
277
pm.setMask( d_data->contentsMask );
279
painter.begin( this );
280
painter.setClipRegion( pe->region() );
281
painter.drawPixmap( 0, 0, pm );
285
\brief Calculate a mask for the contents of the panned widget
287
Sometimes only parts of the contents of a widget should be
288
panned. F.e. for a widget with a styled background with rounded borders
289
only the area inside of the border should be panned.
291
\return An empty bitmap, indicating no mask
293
QBitmap QwtPanner::contentsMask() const
299
Grab the widget into a pixmap.
301
QPixmap QwtPanner::grab() const
303
return QPixmap::grabWidget( parentWidget() );
309
When isEnabled() the mouse events of the observed widget are filtered.
311
\sa widgetMousePressEvent(), widgetMouseReleaseEvent(),
312
widgetMouseMoveEvent()
314
bool QwtPanner::eventFilter( QObject *o, QEvent *e )
316
if ( o == NULL || o != parentWidget() )
321
case QEvent::MouseButtonPress:
323
widgetMousePressEvent( ( QMouseEvent * )e );
326
case QEvent::MouseMove:
328
widgetMouseMoveEvent( ( QMouseEvent * )e );
331
case QEvent::MouseButtonRelease:
333
widgetMouseReleaseEvent( ( QMouseEvent * )e );
336
case QEvent::KeyPress:
338
widgetKeyPressEvent( ( QKeyEvent * )e );
341
case QEvent::KeyRelease:
343
widgetKeyReleaseEvent( ( QKeyEvent * )e );
359
Handle a mouse press event for the observed widget.
361
\param me Mouse event
362
\sa eventFilter(), widgetMouseReleaseEvent(),
363
widgetMouseMoveEvent(),
365
void QwtPanner::widgetMousePressEvent( QMouseEvent *me )
367
if ( me->button() != d_data->button )
370
QWidget *w = parentWidget();
374
if ( ( me->modifiers() & Qt::KeyboardModifierMask ) !=
375
( int )( d_data->buttonState & Qt::KeyboardModifierMask ) )
384
d_data->initialPos = d_data->pos = me->pos();
386
setGeometry( parentWidget()->rect() );
388
// We don't want to grab the picker !
389
QVector<QwtPicker *> pickers = qwtActivePickers( parentWidget() );
390
for ( int i = 0; i < ( int )pickers.size(); i++ )
391
pickers[i]->setEnabled( false );
393
d_data->pixmap = grab();
394
d_data->contentsMask = contentsMask();
396
for ( int i = 0; i < ( int )pickers.size(); i++ )
397
pickers[i]->setEnabled( true );
403
Handle a mouse move event for the observed widget.
405
\param me Mouse event
406
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent()
408
void QwtPanner::widgetMouseMoveEvent( QMouseEvent *me )
413
QPoint pos = me->pos();
414
if ( !isOrientationEnabled( Qt::Horizontal ) )
415
pos.setX( d_data->initialPos.x() );
416
if ( !isOrientationEnabled( Qt::Vertical ) )
417
pos.setY( d_data->initialPos.y() );
419
if ( pos != d_data->pos && rect().contains( pos ) )
424
Q_EMIT moved( d_data->pos.x() - d_data->initialPos.x(),
425
d_data->pos.y() - d_data->initialPos.y() );
430
Handle a mouse release event for the observed widget.
432
\param me Mouse event
433
\sa eventFilter(), widgetMousePressEvent(),
434
widgetMouseMoveEvent(),
436
void QwtPanner::widgetMouseReleaseEvent( QMouseEvent *me )
445
QPoint pos = me->pos();
446
if ( !isOrientationEnabled( Qt::Horizontal ) )
447
pos.setX( d_data->initialPos.x() );
448
if ( !isOrientationEnabled( Qt::Vertical ) )
449
pos.setY( d_data->initialPos.y() );
451
d_data->pixmap = QPixmap();
452
d_data->contentsMask = QBitmap();
455
if ( d_data->pos != d_data->initialPos )
457
Q_EMIT panned( d_data->pos.x() - d_data->initialPos.x(),
458
d_data->pos.y() - d_data->initialPos.y() );
464
Handle a key press event for the observed widget.
467
\sa eventFilter(), widgetKeyReleaseEvent()
469
void QwtPanner::widgetKeyPressEvent( QKeyEvent *ke )
471
if ( ke->key() == d_data->abortKey )
474
( ke->modifiers() & Qt::KeyboardModifierMask ) ==
475
( int )( d_data->abortKeyState & Qt::KeyboardModifierMask );
482
d_data->pixmap = QPixmap();
488
Handle a key release event for the observed widget.
489
\sa eventFilter(), widgetKeyReleaseEvent()
491
void QwtPanner::widgetKeyReleaseEvent( QKeyEvent * )
496
void QwtPanner::showCursor( bool on )
498
if ( on == d_data->hasCursor )
501
QWidget *w = parentWidget();
502
if ( w == NULL || d_data->cursor == NULL )
505
d_data->hasCursor = on;
509
if ( w->testAttribute( Qt::WA_SetCursor ) )
511
delete d_data->restoreCursor;
512
d_data->restoreCursor = new QCursor( w->cursor() );
514
w->setCursor( *d_data->cursor );
518
if ( d_data->restoreCursor )
520
w->setCursor( *d_data->restoreCursor );
521
delete d_data->restoreCursor;
522
d_data->restoreCursor = NULL;