src/gui/widgets/qfocusframe.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 "qfocusframe.h"
       
    43 #include "qstyle.h"
       
    44 #include "qbitmap.h"
       
    45 #include "qstylepainter.h"
       
    46 #include "qstyleoption.h"
       
    47 #include "qdebug.h"
       
    48 #include <private/qwidget_p.h>
       
    49 
       
    50 QT_BEGIN_NAMESPACE
       
    51 
       
    52 class QFocusFramePrivate : public QWidgetPrivate
       
    53 {
       
    54     Q_DECLARE_PUBLIC(QFocusFrame)
       
    55     QWidget *widget;
       
    56 
       
    57 public:
       
    58     QFocusFramePrivate() {
       
    59         widget = 0;
       
    60         sendChildEvents = false;
       
    61     }
       
    62     void updateSize();
       
    63     void update();
       
    64 };
       
    65 
       
    66 void QFocusFramePrivate::update()
       
    67 {
       
    68     Q_Q(QFocusFrame);
       
    69     q->setParent(widget->parentWidget());
       
    70     updateSize();
       
    71     if (q->parentWidget()->rect().intersects(q->geometry())) {
       
    72         if (q->style()->styleHint(QStyle::SH_FocusFrame_AboveWidget, 0, q))
       
    73             q->raise();
       
    74         else
       
    75             q->stackUnder(widget);
       
    76         q->show();
       
    77     } else {
       
    78         q->hide();
       
    79     }
       
    80 }
       
    81 
       
    82 void QFocusFramePrivate::updateSize()
       
    83 {
       
    84     Q_Q(QFocusFrame);
       
    85     int vmargin = q->style()->pixelMetric(QStyle::PM_FocusFrameVMargin),
       
    86         hmargin = q->style()->pixelMetric(QStyle::PM_FocusFrameHMargin);
       
    87     QRect geom(widget->x()-hmargin, widget->y()-vmargin,
       
    88                widget->width()+(hmargin*2), widget->height()+(vmargin*2));
       
    89     if(q->geometry() == geom)
       
    90         return;
       
    91 
       
    92     q->setGeometry(geom);
       
    93     QStyleHintReturnMask mask;
       
    94     QStyleOption opt;
       
    95     q->initStyleOption(&opt);
       
    96     if (q->style()->styleHint(QStyle::SH_FocusFrame_Mask, &opt, q, &mask))
       
    97         q->setMask(mask.region);
       
    98 }
       
    99 
       
   100 /*!
       
   101     Initialize \a option with the values from this QFocusFrame. This method is useful
       
   102     for subclasses when they need a QStyleOption, but don't want to fill
       
   103     in all the information themselves.
       
   104 
       
   105     \sa QStyleOption::initFrom()
       
   106 */
       
   107 void QFocusFrame::initStyleOption(QStyleOption *option) const
       
   108 {
       
   109     if (!option)
       
   110         return;
       
   111 
       
   112     option->initFrom(this);
       
   113 }
       
   114 
       
   115 /*!
       
   116     \class QFocusFrame
       
   117     \brief The QFocusFrame widget provides a focus frame which can be
       
   118     outside of a widget's normal paintable area.
       
   119 
       
   120     \ingroup basicwidgets
       
   121 
       
   122 
       
   123     Normally an application will not need to create its own
       
   124     QFocusFrame as QStyle will handle this detail for
       
   125     you. A style writer can optionally use a QFocusFrame to have a
       
   126     focus area outside of the widget's paintable geometry. In this way
       
   127     space need not be reserved for the widget to have focus but only
       
   128     set on a QWidget with QFocusFrame::setWidget. It is, however,
       
   129     legal to create your own QFocusFrame on a custom widget and set
       
   130     its geometry manually via QWidget::setGeometry however you will
       
   131     not get auto-placement when the focused widget changes size or
       
   132     placement.
       
   133 */
       
   134 
       
   135 /*!
       
   136     Constructs a QFocusFrame.
       
   137 
       
   138     The focus frame will not monitor \a parent for updates but rather
       
   139     can be placed manually or by using QFocusFrame::setWidget. A
       
   140     QFocusFrame sets Qt::WA_NoChildEventsForParent attribute; as a
       
   141     result the parent will not receive a QEvent::ChildInserted event,
       
   142     this will make it possible to manually set the geometry of the
       
   143     QFocusFrame inside of a QSplitter or other child event monitoring
       
   144     widget.
       
   145 
       
   146     \sa QFocusFrame::setWidget()
       
   147 */
       
   148 
       
   149 QFocusFrame::QFocusFrame(QWidget *parent)
       
   150     : QWidget(*new QFocusFramePrivate, parent, 0)
       
   151 {
       
   152     setAttribute(Qt::WA_TransparentForMouseEvents);
       
   153     setFocusPolicy(Qt::NoFocus);
       
   154     setAttribute(Qt::WA_NoChildEventsForParent, true);
       
   155     setAttribute(Qt::WA_AcceptDrops, style()->styleHint(QStyle::SH_FocusFrame_AboveWidget, 0, this));
       
   156 }
       
   157 
       
   158 /*!
       
   159     Destructor.
       
   160 */
       
   161 
       
   162 QFocusFrame::~QFocusFrame()
       
   163 {
       
   164 }
       
   165 
       
   166 /*!
       
   167   QFocusFrame will track changes to \a widget and resize itself automatically.
       
   168   If the monitored widget's parent changes, QFocusFrame will follow the widget
       
   169   and place itself around the widget automatically. If the monitored widget is deleted,
       
   170   QFocusFrame will set it to zero.
       
   171 
       
   172   \sa QFocusFrame::widget()
       
   173 */
       
   174 
       
   175 void
       
   176 QFocusFrame::setWidget(QWidget *widget)
       
   177 {
       
   178     Q_D(QFocusFrame);
       
   179     if(widget == d->widget)
       
   180         return;
       
   181 
       
   182     if(d->widget)
       
   183         d->widget->removeEventFilter(this);
       
   184     if(widget && !widget->isWindow() && widget->parentWidget()->windowType() != Qt::SubWindow) {
       
   185         d->widget = widget;
       
   186         widget->installEventFilter(this);
       
   187         d->update();
       
   188     } else {
       
   189         d->widget = 0;
       
   190         hide();
       
   191     }
       
   192 }
       
   193 
       
   194 /*!
       
   195   Returns the currently monitored widget for automatically resize and
       
   196   update.
       
   197 
       
   198    \sa QFocusFrame::setWidget()
       
   199 */
       
   200 
       
   201 QWidget *
       
   202 QFocusFrame::widget() const
       
   203 {
       
   204     Q_D(const QFocusFrame);
       
   205     return d->widget;
       
   206 }
       
   207 
       
   208 
       
   209 /*! \reimp */
       
   210 void
       
   211 QFocusFrame::paintEvent(QPaintEvent *)
       
   212 {
       
   213     QStylePainter p(this);
       
   214     QStyleOption option;
       
   215     initStyleOption(&option);
       
   216     p.drawControl(QStyle::CE_FocusFrame, option);
       
   217 }
       
   218 
       
   219 
       
   220 /*! \reimp */
       
   221 bool
       
   222 QFocusFrame::eventFilter(QObject *o, QEvent *e)
       
   223 {
       
   224     Q_D(QFocusFrame);
       
   225     if(o == d->widget) {
       
   226         switch(e->type()) {
       
   227         case QEvent::Move:
       
   228         case QEvent::Resize:
       
   229             d->updateSize();
       
   230             break;
       
   231         case QEvent::Hide:
       
   232         case QEvent::StyleChange:
       
   233             hide();
       
   234             break;
       
   235         case QEvent::ParentChange:
       
   236             d->update();
       
   237             break;
       
   238         case QEvent::Show:
       
   239             d->update();
       
   240             show();
       
   241             break;
       
   242         case QEvent::PaletteChange:
       
   243             setPalette(d->widget->palette());
       
   244             break;
       
   245         case QEvent::ZOrderChange:
       
   246             if (style()->styleHint(QStyle::SH_FocusFrame_AboveWidget, 0, this))
       
   247                 raise();
       
   248             else
       
   249                 stackUnder(d->widget);
       
   250             break;
       
   251         case QEvent::Destroy:
       
   252             setWidget(0);
       
   253             break;
       
   254         default:
       
   255             break;
       
   256         }
       
   257     }
       
   258     return false;
       
   259 }
       
   260 
       
   261 /*! \reimp */
       
   262 bool QFocusFrame::event(QEvent *e)
       
   263 {
       
   264     return QWidget::event(e);
       
   265 }
       
   266 
       
   267 QT_END_NAMESPACE