source: trunk/src/gui/widgets/qrubberband.cpp@ 1027

Last change on this file since 1027 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 9.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qbitmap.h"
43#include "qevent.h"
44#include "qstylepainter.h"
45#include "qrubberband.h"
46#include "qtimer.h"
47
48#ifndef QT_NO_RUBBERBAND
49
50#include "qstyle.h"
51#include "qstyleoption.h"
52#ifdef Q_WS_MAC
53# include <private/qt_mac_p.h>
54# include <private/qt_cocoa_helpers_mac_p.h>
55#endif
56
57#include <qdebug.h>
58
59#include <private/qwidget_p.h>
60
61QT_BEGIN_NAMESPACE
62
63//### a rubberband window type would be a more elegant solution
64#define RUBBERBAND_WINDOW_TYPE Qt::ToolTip
65
66class QRubberBandPrivate : public QWidgetPrivate
67{
68 Q_DECLARE_PUBLIC(QRubberBand)
69public:
70 QRect rect;
71 QRubberBand::Shape shape;
72 QRegion clipping;
73 void updateMask();
74};
75
76/*!
77 Initialize \a option with the values from this QRubberBand. This method
78 is useful for subclasses when they need a QStyleOptionRubberBand, but don't want
79 to fill in all the information themselves.
80
81 \sa QStyleOption::initFrom()
82*/
83void QRubberBand::initStyleOption(QStyleOptionRubberBand *option) const
84{
85 if (!option)
86 return;
87 option->initFrom(this);
88 option->shape = d_func()->shape;
89#ifndef Q_WS_MAC
90 option->opaque = true;
91#else
92 option->opaque = windowFlags() & RUBBERBAND_WINDOW_TYPE;
93#endif
94}
95
96/*!
97 \class QRubberBand
98 \brief The QRubberBand class provides a rectangle or line that can
99 indicate a selection or a boundary.
100
101 A rubber band is often used to show a new bounding area (as in a
102 QSplitter or a QDockWidget that is undocking). Historically this has
103 been implemented using a QPainter and XOR, but this approach
104 doesn't always work properly since rendering can happen in the
105 window below the rubber band, but before the rubber band has been
106 "erased".
107
108 You can create a QRubberBand whenever you need to render a rubber band
109 around a given area (or to represent a single line), then call
110 setGeometry(), move() or resize() to position and size it. A common
111 pattern is to do this in conjunction with mouse events. For example:
112
113 \snippet doc/src/snippets/code/src_gui_widgets_qrubberband.cpp 0
114
115 If you pass a parent to QRubberBand's constructor, the rubber band will
116 display only inside its parent, but stays on top of other child widgets.
117 If no parent is passed, QRubberBand will act as a top-level widget.
118
119 Call show() to make the rubber band visible; also when the
120 rubber band is not a top-level. Hiding or destroying
121 the widget will make the rubber band disappear. The rubber band
122 can be a \l Rectangle or a \l Line (vertical or horizontal),
123 depending on the shape() it was given when constructed.
124*/
125
126// ### DOC: How about some nice convenience constructors?
127//QRubberBand::QRubberBand(QRubberBand::Type t, const QRect &rect, QWidget *p)
128//QRubberBand::QRubberBand(QRubberBand::Type t, int x, int y, int w, int h, QWidget *p)
129
130/*!
131 Constructs a rubber band of shape \a s, with parent \a p.
132
133 By default a rectangular rubber band (\a s is \c Rectangle) will
134 use a mask, so that a small border of the rectangle is all
135 that is visible. Some styles (e.g., native Mac OS X) will
136 change this and call QWidget::setWindowOpacity() to make a
137 semi-transparent filled selection rectangle.
138*/
139QRubberBand::QRubberBand(Shape s, QWidget *p)
140 : QWidget(*new QRubberBandPrivate, p, (p && p->windowType() != Qt::Desktop) ? Qt::Widget : RUBBERBAND_WINDOW_TYPE)
141{
142 Q_D(QRubberBand);
143 d->shape = s;
144 setAttribute(Qt::WA_TransparentForMouseEvents);
145#ifndef Q_WS_WIN
146 setAttribute(Qt::WA_NoSystemBackground);
147#endif //Q_WS_WIN
148 setAttribute(Qt::WA_WState_ExplicitShowHide);
149 setVisible(false);
150#ifdef Q_WS_MAC
151 if (isWindow()) {
152 createWinId();
153 extern OSWindowRef qt_mac_window_for(const QWidget *); //qwidget_mac.cpp
154 macWindowSetHasShadow(qt_mac_window_for(this), false);
155 }
156#endif
157}
158
159/*!
160 Destructor.
161*/
162QRubberBand::~QRubberBand()
163{
164}
165
166/*!
167 \enum QRubberBand::Shape
168
169 This enum specifies what shape a QRubberBand should have. This is
170 a drawing hint that is passed down to the style system, and can be
171 interpreted by each QStyle.
172
173 \value Line A QRubberBand can represent a vertical or horizontal
174 line. Geometry is still given in rect() and the line
175 will fill the given geometry on most styles.
176
177 \value Rectangle A QRubberBand can represent a rectangle. Some
178 styles will interpret this as a filled (often
179 semi-transparent) rectangle, or a rectangular
180 outline.
181*/
182
183/*!
184 Returns the shape of this rubber band. The shape can only be set
185 upon construction.
186*/
187QRubberBand::Shape QRubberBand::shape() const
188{
189 Q_D(const QRubberBand);
190 return d->shape;
191}
192
193/*!
194 \internal
195*/
196void QRubberBandPrivate::updateMask()
197{
198 Q_Q(QRubberBand);
199 QStyleHintReturnMask mask;
200 QStyleOptionRubberBand opt;
201 q->initStyleOption(&opt);
202 if (q->style()->styleHint(QStyle::SH_RubberBand_Mask, &opt, q, &mask)) {
203 q->setMask(mask.region);
204 } else {
205 q->clearMask();
206 }
207}
208
209/*!
210 \reimp
211*/
212void QRubberBand::paintEvent(QPaintEvent *)
213{
214 QStylePainter painter(this);
215 QStyleOptionRubberBand option;
216 initStyleOption(&option);
217 painter.drawControl(QStyle::CE_RubberBand, option);
218}
219
220/*!
221 \reimp
222*/
223void QRubberBand::changeEvent(QEvent *e)
224{
225 QWidget::changeEvent(e);
226 switch (e->type()) {
227 case QEvent::ParentChange:
228 if (parent()) {
229 setWindowFlags(windowFlags() & ~RUBBERBAND_WINDOW_TYPE);
230 } else {
231 setWindowFlags(windowFlags() | RUBBERBAND_WINDOW_TYPE);
232 }
233 break;
234 default:
235 break;
236 }
237
238 if (e->type() == QEvent::ZOrderChange)
239 raise();
240}
241
242/*!
243 \reimp
244*/
245void QRubberBand::showEvent(QShowEvent *e)
246{
247 raise();
248 e->ignore();
249}
250
251/*!
252 \reimp
253*/
254void QRubberBand::resizeEvent(QResizeEvent *)
255{
256 Q_D(QRubberBand);
257 d->updateMask();
258}
259
260/*!
261 \reimp
262*/
263void QRubberBand::moveEvent(QMoveEvent *)
264{
265 Q_D(QRubberBand);
266 d->updateMask();
267}
268
269/*!
270 \fn void QRubberBand::move(const QPoint &p);
271
272 \overload
273
274 Moves the rubberband to point \a p.
275
276 \sa resize()
277*/
278
279/*!
280 \fn void QRubberBand::move(int x, int y);
281
282 Moves the rubberband to point (\a x, \a y).
283
284 \sa resize()
285*/
286
287/*!
288 \fn void QRubberBand::resize(const QSize &size);
289
290 \overload
291
292 Resizes the rubberband so that its new size is \a size.
293
294 \sa move()
295*/
296
297/*!
298 \fn void QRubberBand::resize(int width, int height);
299
300 Resizes the rubberband so that its width is \a width, and its
301 height is \a height.
302
303 \sa move()
304*/
305
306/*!
307 \fn void QRubberBand::setGeometry(const QRect &rect)
308
309 Sets the geometry of the rubber band to \a rect, specified in the coordinate system
310 of its parent widget.
311
312 \sa QWidget::geometry
313*/
314void QRubberBand::setGeometry(const QRect &geom)
315{
316 QWidget::setGeometry(geom);
317}
318
319/*!
320 \fn void QRubberBand::setGeometry(int x, int y, int width, int height)
321 \overload
322
323 Sets the geometry of the rubberband to the rectangle whose top-left corner lies at
324 the point (\a x, \a y), and with dimensions specified by \a width and \a height.
325 The geometry is specified in the parent widget's coordinate system.
326*/
327
328/*! \reimp */
329bool QRubberBand::event(QEvent *e)
330{
331 return QWidget::event(e);
332}
333
334QT_END_NAMESPACE
335
336#endif // QT_NO_RUBBERBAND
Note: See TracBrowser for help on using the repository browser.