source: trunk/src/gui/widgets/qframe.cpp@ 460

Last change on this file since 460 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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