src/gui/widgets/qrubberband.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    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 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    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 
       
    61 QT_BEGIN_NAMESPACE
       
    62 
       
    63 //### a rubberband window type would be a more elegant solution
       
    64 #define RUBBERBAND_WINDOW_TYPE Qt::ToolTip
       
    65 
       
    66 class QRubberBandPrivate : public QWidgetPrivate
       
    67 {
       
    68     Q_DECLARE_PUBLIC(QRubberBand)
       
    69 public:
       
    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 */
       
    83 void 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 */
       
   139 QRubberBand::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 */
       
   162 QRubberBand::~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 */
       
   187 QRubberBand::Shape QRubberBand::shape() const
       
   188 {
       
   189     Q_D(const QRubberBand);
       
   190     return d->shape;
       
   191 }
       
   192 
       
   193 /*!
       
   194     \internal
       
   195 */
       
   196 void 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 */
       
   212 void 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 */
       
   223 void 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 */
       
   245 void QRubberBand::showEvent(QShowEvent *e)
       
   246 {
       
   247     raise();
       
   248     e->ignore();
       
   249 }
       
   250 
       
   251 /*!
       
   252     \reimp
       
   253 */
       
   254 void QRubberBand::resizeEvent(QResizeEvent *)
       
   255 {
       
   256     Q_D(QRubberBand);
       
   257     d->updateMask();
       
   258 }
       
   259 
       
   260 /*!
       
   261     \reimp
       
   262 */
       
   263 void 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 */
       
   314 void 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 */
       
   329 bool QRubberBand::event(QEvent *e)
       
   330 {
       
   331     return QWidget::event(e);
       
   332 }
       
   333 
       
   334 QT_END_NAMESPACE
       
   335 
       
   336 #endif // QT_NO_RUBBERBAND