src/gui/widgets/qframe.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 "qframe.h"
       
    43 #include "qbitmap.h"
       
    44 #include "qdrawutil.h"
       
    45 #include "qevent.h"
       
    46 #include "qpainter.h"
       
    47 #include "qstyle.h"
       
    48 #include "qstyleoption.h"
       
    49 #include "qapplication.h"
       
    50 
       
    51 #include "qframe_p.h"
       
    52 
       
    53 QT_BEGIN_NAMESPACE
       
    54 
       
    55 QFramePrivate::QFramePrivate()
       
    56     : frect(QRect(0, 0, 0, 0)),
       
    57       frameStyle(QFrame::NoFrame | QFrame::Plain),
       
    58       lineWidth(1),
       
    59       midLineWidth(0),
       
    60       frameWidth(0),
       
    61       leftFrameWidth(0), rightFrameWidth(0),
       
    62       topFrameWidth(0), bottomFrameWidth(0)
       
    63 {
       
    64 }
       
    65 
       
    66 inline void QFramePrivate::init()
       
    67 {
       
    68     setLayoutItemMargins(QStyle::SE_FrameLayoutItem);
       
    69 }
       
    70 
       
    71 /*!
       
    72     \class QFrame
       
    73     \brief The QFrame class is the base class of widgets that can have a frame.
       
    74 
       
    75     \ingroup abstractwidgets
       
    76 
       
    77 
       
    78     QMenu uses this to "raise" the menu above the surrounding
       
    79     screen. QProgressBar has a "sunken" look. QLabel has a flat look.
       
    80     The frames of widgets like these can be changed.
       
    81 
       
    82     \snippet doc/src/snippets/code/src_gui_widgets_qframe.cpp 0
       
    83 
       
    84     The QFrame class can also be used directly for creating simple
       
    85     placeholder frames without any contents.
       
    86 
       
    87     The frame style is specified by a \l{QFrame::Shape}{frame shape} and
       
    88     a \l{QFrame::Shadow}{shadow style} that is used to visually separate
       
    89     the frame from surrounding widgets. These properties can be set
       
    90     together using the setFrameStyle() function and read with frameStyle().
       
    91 
       
    92     The frame shapes are \l NoFrame, \l Box, \l Panel, \l StyledPanel,
       
    93     HLine and \l VLine; the shadow styles are \l Plain, \l Raised and
       
    94     \l Sunken.
       
    95 
       
    96     A frame widget has three attributes that describe the thickness of the
       
    97     border: \l lineWidth, \l midLineWidth, and \l frameWidth.
       
    98 
       
    99     \list
       
   100     \o The line width is the width of the frame border. It can be modified
       
   101        to customize the frame's appearance.
       
   102 
       
   103     \o The mid-line width specifies the width of an extra line in the
       
   104        middle of the frame, which uses a third color to obtain a special
       
   105        3D effect. Notice that a mid-line is only drawn for \l Box, \l
       
   106        HLine and \l VLine frames that are raised or sunken.
       
   107 
       
   108     \o The frame width is determined by the frame style, and the frameWidth()
       
   109        function is used to obtain the value defined for the style used.
       
   110     \endlist
       
   111 
       
   112     The margin between the frame and the contents of the frame can be
       
   113     customized with the QWidget::setContentsMargins() function.
       
   114 
       
   115     \target picture
       
   116     This table shows some of the combinations of styles and line widths:
       
   117 
       
   118     \image frames.png Table of frame styles
       
   119 */
       
   120 
       
   121 
       
   122 /*!
       
   123     \enum QFrame::Shape
       
   124 
       
   125     This enum type defines the shapes of frame available.
       
   126 
       
   127     \value NoFrame  QFrame draws nothing
       
   128     \value Box  QFrame draws a box around its contents
       
   129     \value Panel  QFrame draws a panel to make the contents appear
       
   130     raised or sunken
       
   131     \value StyledPanel  draws a rectangular panel with a look that
       
   132     depends on the current GUI style. It can be raised or sunken.
       
   133     \value HLine  QFrame draws a horizontal line that frames nothing
       
   134     (useful as separator)
       
   135     \value VLine  QFrame draws a vertical line that frames nothing
       
   136     (useful as separator)
       
   137     \value WinPanel draws a rectangular panel that can be raised or
       
   138     sunken like those in Windows 2000. Specifying this shape sets
       
   139     the line width to 2 pixels. WinPanel is provided for compatibility.
       
   140     For GUI style independence we recommend using StyledPanel instead.
       
   141 
       
   142     \omitvalue GroupBoxPanel
       
   143     \omitvalue ToolBarPanel
       
   144     \omitvalue MenuBarPanel
       
   145     \omitvalue PopupPanel
       
   146     \omitvalue LineEditPanel
       
   147     \omitvalue TabWidgetPanel
       
   148 
       
   149     When it does not call QStyle, Shape interacts with QFrame::Shadow,
       
   150     the lineWidth() and the midLineWidth() to create the total result.
       
   151     See the picture of the frames in the main class documentation.
       
   152 
       
   153     \sa QFrame::Shadow QFrame::style() QStyle::drawPrimitive()
       
   154 */
       
   155 
       
   156 
       
   157 /*!
       
   158     \enum QFrame::Shadow
       
   159 
       
   160     This enum type defines the types of shadow that are used to give
       
   161     a 3D effect to frames.
       
   162 
       
   163     \value Plain  the frame and contents appear level with the
       
   164     surroundings; draws using the palette QPalette::WindowText color
       
   165     (without any 3D effect)
       
   166 
       
   167     \value Raised the frame and contents appear raised; draws a 3D
       
   168     raised line using the light and dark colors of the current color
       
   169     group
       
   170     \value Sunken the frame and contents appear sunken; draws a 3D
       
   171     sunken line using the light and dark colors of the current color
       
   172     group
       
   173 
       
   174     Shadow interacts with QFrame::Shape, the lineWidth() and the
       
   175     midLineWidth(). See the picture of the frames in the main class
       
   176     documentation.
       
   177 
       
   178     \sa QFrame::Shape lineWidth() midLineWidth()
       
   179 */
       
   180 
       
   181 /*!
       
   182     \enum QFrame::StyleMask
       
   183 
       
   184     This enum defines two constants that can be used to extract the
       
   185     two components of frameStyle():
       
   186 
       
   187     \value Shadow_Mask The \l Shadow part of frameStyle()
       
   188     \value Shape_Mask  The \l Shape part of frameStyle()
       
   189 
       
   190     \omitvalue MShadow
       
   191     \omitvalue MShape
       
   192 
       
   193     Normally, you don't need to use these, since frameShadow() and
       
   194     frameShape() already extract the \l Shadow and the \l Shape parts
       
   195     of frameStyle().
       
   196 
       
   197     \sa frameStyle(), setFrameStyle()
       
   198 */
       
   199 
       
   200 /*!
       
   201     Constructs a frame widget with frame style \l NoFrame and a
       
   202     1-pixel frame width.
       
   203 
       
   204     The \a parent and \a f arguments are passed to the QWidget
       
   205     constructor.
       
   206 */
       
   207 
       
   208 QFrame::QFrame(QWidget* parent, Qt::WindowFlags f)
       
   209     : QWidget(*new QFramePrivate, parent, f)
       
   210 {
       
   211     Q_D(QFrame);
       
   212     d->init();
       
   213 }
       
   214 
       
   215 /*! \internal */
       
   216 QFrame::QFrame(QFramePrivate &dd, QWidget* parent, Qt::WindowFlags f)
       
   217     : QWidget(dd, parent, f)
       
   218 {
       
   219     Q_D(QFrame);
       
   220     d->init();
       
   221 }
       
   222 
       
   223 #ifdef QT3_SUPPORT
       
   224 /*!
       
   225     Use one of the constructors that doesn't take the \a name
       
   226     argument and then use setObjectName() instead.
       
   227 */
       
   228 QFrame::QFrame(QWidget *parent, const char *name, Qt::WindowFlags f)
       
   229     : QWidget(*new QFramePrivate, parent, f)
       
   230 {
       
   231     Q_D(QFrame);
       
   232     setObjectName(QString::fromAscii(name));
       
   233     d->init();
       
   234 }
       
   235 #endif
       
   236 
       
   237 /*!
       
   238   Destroys the frame.
       
   239  */
       
   240 QFrame::~QFrame()
       
   241 {
       
   242 }
       
   243 
       
   244 /*!
       
   245     Returns the frame style.
       
   246 
       
   247     The default value is QFrame::NoFrame.
       
   248 
       
   249     \sa setFrameStyle(), frameShape(), frameShadow()
       
   250 */
       
   251 int QFrame::frameStyle() const
       
   252 {
       
   253     Q_D(const QFrame);
       
   254     return d->frameStyle;
       
   255 }
       
   256 
       
   257 /*!
       
   258     \property QFrame::frameShape
       
   259     \brief the frame shape value from the frame style
       
   260 
       
   261     \sa frameStyle(), frameShadow()
       
   262 */
       
   263 
       
   264 QFrame::Shape QFrame::frameShape() const
       
   265 {
       
   266     Q_D(const QFrame);
       
   267     return (Shape) (d->frameStyle & Shape_Mask);
       
   268 }
       
   269 
       
   270 void QFrame::setFrameShape(QFrame::Shape s)
       
   271 {
       
   272     Q_D(QFrame);
       
   273     setFrameStyle((d->frameStyle & Shadow_Mask) | s);
       
   274 }
       
   275 
       
   276 
       
   277 /*!
       
   278     \property QFrame::frameShadow
       
   279     \brief the frame shadow value from the frame style
       
   280 
       
   281     \sa frameStyle(), frameShape()
       
   282 */
       
   283 QFrame::Shadow QFrame::frameShadow() const
       
   284 {
       
   285     Q_D(const QFrame);
       
   286     return (Shadow) (d->frameStyle & Shadow_Mask);
       
   287 }
       
   288 
       
   289 void QFrame::setFrameShadow(QFrame::Shadow s)
       
   290 {
       
   291     Q_D(QFrame);
       
   292     setFrameStyle((d->frameStyle & Shape_Mask) | s);
       
   293 }
       
   294 
       
   295 /*!
       
   296     Sets the frame style to \a style.
       
   297 
       
   298     The \a style is the bitwise OR between a frame shape and a frame
       
   299     shadow style. See the picture of the frames in the main class
       
   300     documentation.
       
   301 
       
   302     The frame shapes are given in \l{QFrame::Shape} and the shadow
       
   303     styles in \l{QFrame::Shadow}.
       
   304 
       
   305     If a mid-line width greater than 0 is specified, an additional
       
   306     line is drawn for \l Raised or \l Sunken \l Box, \l HLine, and \l
       
   307     VLine frames. The mid-color of the current color group is used for
       
   308     drawing middle lines.
       
   309 
       
   310     \sa frameStyle()
       
   311 */
       
   312 
       
   313 void QFrame::setFrameStyle(int style)
       
   314 {
       
   315     Q_D(QFrame);
       
   316     if (!testAttribute(Qt::WA_WState_OwnSizePolicy)) {
       
   317         QSizePolicy sp;
       
   318 
       
   319         switch (style & Shape_Mask) {
       
   320         case HLine:
       
   321             sp = QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed, QSizePolicy::Line);
       
   322             break;
       
   323         case VLine:
       
   324             sp = QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum, QSizePolicy::Line);
       
   325             break;
       
   326         default:
       
   327             sp = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::Frame);
       
   328         }
       
   329         setSizePolicy(sp);
       
   330         setAttribute(Qt::WA_WState_OwnSizePolicy, false);
       
   331     }
       
   332     d->frameStyle = (short)style;
       
   333     update();
       
   334     d->updateFrameWidth();
       
   335 }
       
   336 
       
   337 /*!
       
   338     \property QFrame::lineWidth
       
   339     \brief the line width
       
   340 
       
   341     Note that the \e total line width for frames used as separators
       
   342     (\l HLine and \l VLine) is specified by \l frameWidth.
       
   343 
       
   344     The default value is 1.
       
   345 
       
   346     \sa midLineWidth, frameWidth
       
   347 */
       
   348 
       
   349 void QFrame::setLineWidth(int w)
       
   350 {
       
   351     Q_D(QFrame);
       
   352     if (short(w) == d->lineWidth)
       
   353         return;
       
   354     d->lineWidth = short(w);
       
   355     d->updateFrameWidth();
       
   356 }
       
   357 
       
   358 int QFrame::lineWidth() const
       
   359 {
       
   360     Q_D(const QFrame);
       
   361     return d->lineWidth;
       
   362 }
       
   363 
       
   364 /*!
       
   365     \property QFrame::midLineWidth
       
   366     \brief the width of the mid-line
       
   367 
       
   368     The default value is 0.
       
   369 
       
   370     \sa lineWidth, frameWidth
       
   371 */
       
   372 
       
   373 void QFrame::setMidLineWidth(int w)
       
   374 {
       
   375     Q_D(QFrame);
       
   376     if (short(w) == d->midLineWidth)
       
   377         return;
       
   378     d->midLineWidth = short(w);
       
   379     d->updateFrameWidth();
       
   380 }
       
   381 
       
   382 int QFrame::midLineWidth() const
       
   383 {
       
   384     Q_D(const QFrame);
       
   385     return d->midLineWidth;
       
   386 }
       
   387 
       
   388 /*!
       
   389   \internal
       
   390   Updates the frame widths from the style.
       
   391 */
       
   392 void QFramePrivate::updateStyledFrameWidths()
       
   393 {
       
   394     Q_Q(const QFrame);
       
   395     QStyleOptionFrameV3 opt;
       
   396     opt.initFrom(q);
       
   397     opt.lineWidth = lineWidth;
       
   398     opt.midLineWidth = midLineWidth;
       
   399     opt.frameShape = QFrame::Shape(frameStyle & QFrame::Shape_Mask);
       
   400 
       
   401     QRect cr = q->style()->subElementRect(QStyle::SE_ShapedFrameContents, &opt, q);
       
   402     leftFrameWidth = cr.left() - opt.rect.left();
       
   403     topFrameWidth = cr.top() - opt.rect.top();
       
   404     rightFrameWidth = opt.rect.right() - cr.right(),
       
   405     bottomFrameWidth = opt.rect.bottom() - cr.bottom();
       
   406     frameWidth = qMax(qMax(leftFrameWidth, rightFrameWidth),
       
   407                       qMax(topFrameWidth, bottomFrameWidth));
       
   408 }
       
   409 
       
   410 /*!
       
   411   \internal
       
   412   Updated the frameWidth parameter.
       
   413 */
       
   414 
       
   415 void QFramePrivate::updateFrameWidth()
       
   416 {
       
   417     Q_Q(QFrame);
       
   418     QRect fr = q->frameRect();
       
   419     updateStyledFrameWidths();
       
   420     q->setFrameRect(fr);
       
   421     setLayoutItemMargins(QStyle::SE_FrameLayoutItem);
       
   422 }
       
   423 
       
   424 /*!
       
   425     \property QFrame::frameWidth
       
   426     \brief the width of the frame that is drawn.
       
   427 
       
   428     Note that the frame width depends on the \l{QFrame::setFrameStyle()}{frame style},
       
   429     not only the line width and the mid-line width. For example, the style specified
       
   430     by \l NoFrame always has a frame width of 0, whereas the style \l Panel has a
       
   431     frame width equivalent to the line width.
       
   432 
       
   433     \sa lineWidth(), midLineWidth(), frameStyle()
       
   434 */
       
   435 int QFrame::frameWidth() const
       
   436 {
       
   437     Q_D(const QFrame);
       
   438     return d->frameWidth;
       
   439 }
       
   440 
       
   441 
       
   442 /*!
       
   443     \property QFrame::frameRect
       
   444     \brief the frame's rectangle
       
   445 
       
   446     The frame's rectangle is the rectangle the frame is drawn in. By
       
   447     default, this is the entire widget. Setting the rectangle does
       
   448     does \e not cause a widget update. The frame rectangle is
       
   449     automatically adjusted when the widget changes size.
       
   450 
       
   451     If you set the rectangle to a null rectangle (for example,
       
   452     QRect(0, 0, 0, 0)), then the resulting frame rectangle is
       
   453     equivalent to the \link QWidget::rect() widget rectangle\endlink.
       
   454 */
       
   455 
       
   456 QRect QFrame::frameRect() const
       
   457 {
       
   458     Q_D(const QFrame);
       
   459     QRect fr = contentsRect();
       
   460     fr.adjust(-d->leftFrameWidth, -d->topFrameWidth, d->rightFrameWidth, d->bottomFrameWidth);
       
   461     return fr;
       
   462 }
       
   463 
       
   464 void QFrame::setFrameRect(const QRect &r)
       
   465 {
       
   466     Q_D(QFrame);
       
   467     QRect cr = r.isValid() ? r : rect();
       
   468     cr.adjust(d->leftFrameWidth, d->topFrameWidth, -d->rightFrameWidth, -d->bottomFrameWidth);
       
   469     setContentsMargins(cr.left(), cr.top(), rect().right() - cr.right(), rect().bottom() - cr.bottom());
       
   470 }
       
   471 
       
   472 /*!\reimp
       
   473 */
       
   474 QSize QFrame::sizeHint() const
       
   475 {
       
   476     Q_D(const QFrame);
       
   477     //   Returns a size hint for the frame - for HLine and VLine
       
   478     //   shapes, this is stretchable one way and 3 pixels wide the
       
   479     //   other.  For other shapes, QWidget::sizeHint() is used.
       
   480     switch (d->frameStyle & Shape_Mask) {
       
   481     case HLine:
       
   482         return QSize(-1,3);
       
   483     case VLine:
       
   484         return QSize(3,-1);
       
   485     default:
       
   486         return QWidget::sizeHint();
       
   487     }
       
   488 }
       
   489 
       
   490 /*!\reimp
       
   491 */
       
   492 
       
   493 void QFrame::paintEvent(QPaintEvent *)
       
   494 {
       
   495     QPainter paint(this);
       
   496     drawFrame(&paint);
       
   497 }
       
   498 
       
   499 /*!
       
   500     \internal
       
   501 
       
   502     Mostly for the sake of Q3Frame
       
   503  */
       
   504 void QFrame::drawFrame(QPainter *p)
       
   505 {
       
   506     Q_D(QFrame);
       
   507     QStyleOptionFrameV3 opt;
       
   508     opt.init(this);
       
   509     int frameShape  = d->frameStyle & QFrame::Shape_Mask;
       
   510     int frameShadow = d->frameStyle & QFrame::Shadow_Mask;
       
   511     opt.frameShape = Shape(int(opt.frameShape) | frameShape);
       
   512     opt.rect = frameRect();
       
   513     switch (frameShape) {
       
   514         case QFrame::Box:
       
   515         case QFrame::HLine:
       
   516         case QFrame::VLine:
       
   517         case QFrame::StyledPanel:
       
   518         case QFrame::Panel:
       
   519             opt.lineWidth = d->lineWidth;
       
   520             opt.midLineWidth = d->midLineWidth;
       
   521             break;
       
   522         default:
       
   523             // most frame styles do not handle customized line and midline widths
       
   524             // (see updateFrameWidth()).
       
   525             opt.lineWidth = d->frameWidth;
       
   526             break;
       
   527     }
       
   528 
       
   529     if (frameShadow == Sunken)
       
   530         opt.state |= QStyle::State_Sunken;
       
   531     else if (frameShadow == Raised)
       
   532         opt.state |= QStyle::State_Raised;
       
   533 
       
   534     style()->drawControl(QStyle::CE_ShapedFrame, &opt, p, this);
       
   535 }
       
   536 
       
   537 
       
   538 /*!\reimp
       
   539  */
       
   540 void QFrame::changeEvent(QEvent *ev)
       
   541 {
       
   542     Q_D(QFrame);
       
   543     if (ev->type() == QEvent::StyleChange
       
   544 #ifdef Q_WS_MAC
       
   545             || ev->type() == QEvent::MacSizeChange
       
   546 #endif
       
   547             )
       
   548         d->updateFrameWidth();
       
   549     QWidget::changeEvent(ev);
       
   550 }
       
   551 
       
   552 /*! \reimp */
       
   553 bool QFrame::event(QEvent *e)
       
   554 {
       
   555     if (e->type() == QEvent::ParentChange)
       
   556         d_func()->updateFrameWidth();
       
   557     bool result = QWidget::event(e);
       
   558     //this has to be done after the widget has been polished
       
   559     if (e->type() == QEvent::Polish)
       
   560         d_func()->updateFrameWidth();
       
   561     return result;
       
   562 }
       
   563 
       
   564 QT_END_NAMESPACE