source: trunk/src/widgets/qframe.cpp@ 8

Last change on this file since 8 was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 21.0 KB
Line 
1/****************************************************************************
2** $Id: qframe.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of QFrame widget class
5**
6** Created : 950201
7**
8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9**
10** This file is part of the widgets module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "qframe.h"
39#ifndef QT_NO_FRAME
40#include "qpainter.h"
41#include "qdrawutil.h"
42#include "qframe.h"
43#include "qbitmap.h"
44#include "qstyle.h"
45
46/*!
47 \class QFrame
48 \brief The QFrame class is the base class of widgets that can have a frame.
49
50 \ingroup abstractwidgets
51
52 It draws a frame and calls a virtual function, drawContents(), to
53 fill in the frame. This function is reimplemented by subclasses.
54 There are also two other less useful functions: drawFrame() and
55 frameChanged().
56
57 QPopupMenu uses this to "raise" the menu above the surrounding
58 screen. QProgressBar has a "sunken" look. QLabel has a flat look.
59 The frames of widgets like these can be changed.
60
61 \code
62 QLabel label(...);
63 label.setFrameStyle( QFrame::Panel | QFrame::Raised );
64 label.setLineWidth( 2 );
65
66 QProgressBar pbar(...);
67 label.setFrameStyle( QFrame::NoFrame );
68 \endcode
69
70 The QFrame class can also be used directly for creating simple
71 frames without any contents, although usually you would use a
72 QHBox or QVBox because they automatically lay out the widgets you
73 put inside the frame.
74
75 A frame widget has four attributes: frameStyle(), lineWidth(),
76 midLineWidth(), and margin().
77
78 The frame style is specified by a \link QFrame::Shape frame
79 shape\endlink and a \link QFrame::Shadow shadow style\endlink. The
80 frame shapes are \c NoFrame, \c Box, \c Panel, \c StyledPanel, \c
81 PopupPanel, \c WinPanel, \c ToolBarPanel, \c MenuBarPanel, \c
82 HLine and \c VLine; the shadow styles are \c Plain, \c Raised and
83 \c Sunken.
84
85 The line width is the width of the frame border.
86
87 The mid-line width specifies the width of an extra line in the
88 middle of the frame, which uses a third color to obtain a special
89 3D effect. Notice that a mid-line is only drawn for \c Box, \c
90 HLine and \c VLine frames that are raised or sunken.
91
92 The margin is the gap between the frame and the contents of the
93 frame.
94
95 \target picture
96 This table shows the most useful combinations of styles and widths
97 (and some rather useless ones):
98
99 \img frames.png Table of frame styles
100*/
101
102
103/*!
104 \enum QFrame::Shape
105
106 This enum type defines the shapes of a QFrame's frame.
107
108 \value NoFrame QFrame draws nothing
109 \value Box QFrame draws a box around its contents
110 \value Panel QFrame draws a panel to make the contents appear
111 raised or sunken
112 \value StyledPanel draws a rectangular panel with a look that
113 depends on the current GUI style. It can be raised or sunken.
114 \value HLine QFrame draws a horizontal line that frames nothing
115 (useful as separator)
116 \value VLine QFrame draws a vertical line that frames nothing
117 (useful as separator)
118 \value GroupBoxPanel draws a rectangular panel
119 \value WinPanel draws a rectangular panel that can be raised or
120 sunken like those in Windows 95. Specifying this shape sets
121 the line width to 2 pixels. WinPanel is provided for compatibility.
122 For GUI style independence we recommend using StyledPanel instead.
123 \value ToolBarPanel
124 \value MenuBarPanel
125 \value PopupPanel
126 \value LineEditPanel is used to draw a frame suitable for line edits. The
127 look depends upon the current GUI style.
128 \value TabWidgetPanel is used to draw a frame suitable for tab widgets. The
129 look depends upon the current GUI style.
130 \value MShape internal mask
131
132 When it does not call QStyle, Shape interacts with QFrame::Shadow,
133 the lineWidth() and the midLineWidth() to create the total result.
134 See the \link #picture picture of the frames\endlink in the class
135 description.
136
137 \sa QFrame::Shadow QFrame::style() QStyle::drawPrimitive()
138*/
139
140
141/*!
142 \enum QFrame::Shadow
143
144 This enum type defines the 3D effect used for QFrame's frame.
145
146 \value Plain the frame and contents appear level with the
147 surroundings; draws using the palette foreground color (without
148 any 3D effect)
149 \value Raised the frame and contents appear raised; draws a 3D
150 raised line using the light and dark colors of the current color
151 group
152 \value Sunken the frame and contents appear sunken; draws a 3D
153 sunken line using the light and dark colors of the current color
154 group
155 \value MShadow internal; mask for the shadow
156
157 Shadow interacts with QFrame::Shape, the lineWidth() and the
158 midLineWidth(). See the \link #picture picture of the frames\endlink
159 in the class description.
160
161 \sa QFrame::Shape lineWidth() midLineWidth()
162*/
163
164
165/*!
166 Constructs a frame widget with frame style \c NoFrame and a
167 1-pixel frame width.
168
169 The \a parent, \a name and \a f arguments are passed to the
170 QWidget constructor.
171*/
172
173QFrame::QFrame( QWidget *parent, const char *name, WFlags f )
174 : QWidget( parent, name, f )
175{
176 frect = QRect( 0, 0, 0, 0 );
177 fstyle = NoFrame | Plain;
178 lwidth = 1;
179 mwidth = 0;
180 mlwidth = 0;
181 updateFrameWidth();
182}
183
184static const int wpwidth = 2; // WinPanel lwidth
185
186/*!
187 \fn int QFrame::frameStyle() const
188
189 Returns the frame style.
190
191 The default value is QFrame::NoFrame.
192
193 \sa setFrameStyle(), frameShape(), frameShadow()
194*/
195
196/*!
197 \property QFrame::frameShape
198 \brief the frame shape value from the frame style
199
200 \sa frameStyle(), frameShadow()
201*/
202
203/*!
204 \property QFrame::frameShadow
205 \brief the frame shadow value from the frame style
206
207 \sa frameStyle(), frameShape()
208*/
209
210/*!
211 Sets the frame style to \a style.
212
213 The \a style is the bitwise OR between a frame shape and a frame
214 shadow style. See the \link #picture illustration\endlink in the
215 class documentation.
216
217 The frame shapes are given in \l{QFrame::Shape} and the shadow
218 styles in \l{QFrame::Shadow}.
219
220 If a mid-line width greater than 0 is specified, an additional
221 line is drawn for \c Raised or \c Sunken \c Box, \c HLine, and \c
222 VLine frames. The mid-color of the current color group is used for
223 drawing middle lines.
224
225 \sa \link #picture Illustration\endlink, frameStyle(),
226 colorGroup(), QColorGroup
227*/
228
229void QFrame::setFrameStyle( int style )
230{
231 if ( !testWState( WState_OwnSizePolicy ) ) {
232 switch ( style & MShape ) {
233 case HLine:
234 setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
235 break;
236 case VLine:
237 setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Minimum );
238 break;
239 default:
240 if ( (fstyle & MShape) == HLine || (fstyle & MShape) == VLine)
241 setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
242 }
243 clearWState( WState_OwnSizePolicy );
244 }
245 fstyle = (short)style;
246 updateFrameWidth( TRUE );
247}
248
249/*!
250 \property QFrame::lineWidth
251 \brief the line width
252
253 Note that the \e total line width for \c HLine and \c VLine is
254 given by frameWidth(), not lineWidth().
255
256 The default value is 1.
257
258 \sa midLineWidth(), frameWidth()
259*/
260
261void QFrame::setLineWidth( int w )
262{
263 lwidth = (short)w;
264 updateFrameWidth();
265}
266
267/*!
268 \property QFrame::midLineWidth
269 \brief the width of the mid-line
270
271 The default value is 0.
272
273 \sa lineWidth(), frameWidth()
274*/
275
276void QFrame::setMidLineWidth( int w )
277{
278 mlwidth = (short)w;
279 updateFrameWidth();
280}
281
282
283
284/*!
285 \property QFrame::margin
286 \brief the width of the margin
287
288 The margin is the distance between the innermost pixel of the
289 frame and the outermost pixel of contentsRect(). It is included in
290 frameWidth().
291
292 The margin is filled according to backgroundMode().
293
294 The default value is 0.
295
296 \sa setMargin(), lineWidth(), frameWidth()
297*/
298
299void QFrame::setMargin( int w )
300{
301 mwidth = (short)w;
302 updateFrameWidth();
303}
304
305
306/*!
307 \internal
308 Updated the fwidth parameter.
309*/
310
311void QFrame::updateFrameWidth( bool resetLineMetrics )
312{
313 int frameType = fstyle & MShape;
314 int frameStyle = fstyle & MShadow;
315
316 if ( resetLineMetrics ) {
317 switch ( frameType ) {
318 case MenuBarPanel:
319 mwidth = 0;
320 lwidth = style().pixelMetric( QStyle::PM_MenuBarFrameWidth, this );
321 break;
322 case ToolBarPanel:
323 mwidth = 0;
324 lwidth = style().pixelMetric( QStyle::PM_DockWindowFrameWidth, this );
325 break;
326 case LineEditPanel:
327 case TabWidgetPanel:
328 case PopupPanel:
329 mwidth = 0;
330 lwidth = style().pixelMetric( QStyle::PM_DefaultFrameWidth, this );
331 break;
332 }
333 }
334
335 fwidth = -1;
336
337 switch ( frameType ) {
338
339 case NoFrame:
340 fwidth = 0;
341 break;
342
343 case Box:
344 switch ( frameStyle ) {
345 case Plain:
346 fwidth = lwidth;
347 break;
348 case Raised:
349 case Sunken:
350 fwidth = (short)(lwidth*2 + midLineWidth() );
351 break;
352 }
353 break;
354
355
356 case LineEditPanel:
357 case TabWidgetPanel:
358 case PopupPanel:
359 case GroupBoxPanel:
360 case Panel:
361 case StyledPanel:
362 switch ( frameStyle ) {
363 case Plain:
364 case Raised:
365 case Sunken:
366 fwidth = lwidth;
367 break;
368 }
369 break;
370
371 case WinPanel:
372 switch ( frameStyle ) {
373 case Plain:
374 case Raised:
375 case Sunken:
376 fwidth = wpwidth; //WinPanel does not use lwidth!
377 break;
378 }
379 break;
380 case MenuBarPanel:
381 fwidth = lwidth;
382 break;
383 case ToolBarPanel:
384 fwidth = lwidth;
385 break;
386 case HLine:
387 case VLine:
388 switch ( frameStyle ) {
389 case Plain:
390 fwidth = lwidth;
391 break;
392 case Raised:
393 case Sunken:
394 fwidth = (short)(lwidth*2 + midLineWidth());
395 break;
396 }
397 break;
398 }
399
400 if ( fwidth == -1 ) // invalid style
401 fwidth = 0;
402
403 fwidth += margin();
404
405 frameChanged();
406}
407
408
409/*!
410 \property QFrame::frameWidth
411 \brief the width of the frame that is drawn.
412
413 Note that the frame width depends on the \link
414 QFrame::setFrameStyle() frame style \endlink, not only the line
415 width and the mid-line width. For example, the style \c NoFrame
416 always has a frame width of 0, whereas the style \c Panel has a
417 frame width equivalent to the line width. The frame width also
418 includes the margin.
419
420 \sa lineWidth(), midLineWidth(), frameStyle(), margin()
421*/
422
423/*!
424 \property QFrame::frameRect
425 \brief the frame rectangle
426
427 The frame rectangle is the rectangle the frame is drawn in. By
428 default, this is the entire widget. Setting this property does \e
429 not cause a widget update.
430
431 If this property is set to a null rectangle (for example
432 \c{QRect(0, 0, 0, 0)}), then the frame rectangle is equivalent to
433 the \link QWidget::rect() widget rectangle\endlink.
434
435 \sa contentsRect()
436*/
437
438QRect QFrame::frameRect() const
439{
440 if ( frect.isNull() )
441 return rect();
442 else
443 return frect;
444}
445
446void QFrame::setFrameRect( const QRect &r )
447{
448 frect = r.isValid() ? r : rect();
449}
450
451
452/*!
453 \property QFrame::contentsRect
454 \brief the rectangle inside the frame
455
456 \sa frameRect(), drawContents()
457*/
458
459QRect QFrame::contentsRect() const
460{
461 QRect r = frameRect();
462 int w = frameWidth(); // total width
463 int frameType = fstyle & MShape;
464 if (frameType == PopupPanel) {
465 int vExtra = style().pixelMetric(QStyle::PM_PopupMenuFrameVerticalExtra, this);
466 int hExtra = style().pixelMetric(QStyle::PM_PopupMenuFrameHorizontalExtra, this);
467 r.setRect( r.x()+w+hExtra, r.y()+w+vExtra, r.width()-w*2-hExtra*2, r.height()-w*2-vExtra*2 );
468 } else {
469 r.setRect( r.x()+w, r.y()+w, r.width()-w*2, r.height()-w*2 );
470 }
471 return r;
472}
473
474/*!\reimp
475*/
476QSize QFrame::sizeHint() const
477{
478 // Returns a size hint for the frame - for HLine and VLine
479 // shapes, this is stretchable one way and 3 pixels wide the
480 // other. For other shapes, QWidget::sizeHint() is used.
481 switch (fstyle & MShape) {
482 case HLine:
483 return QSize(-1,3);
484 case VLine:
485 return QSize(3,-1);
486 default:
487 return QWidget::sizeHint();
488 }
489}
490
491/*!
492 Processes the paint event \a event.
493
494 Paints the frame and the contents.
495
496 Opens the painter on the frame and calls drawFrame(), then
497 drawContents().
498*/
499
500void QFrame::paintEvent( QPaintEvent *event )
501{
502 const int m = margin();
503 if ( m && testWFlags( WNoAutoErase ) ) {
504 QRect r = contentsRect();
505 r.addCoords( -m, -m, m, m );
506 erase( event->region().intersect( QRegion( r ) - contentsRect() ) );
507 }
508
509 QPainter paint( this );
510
511 if ( !contentsRect().contains( event->rect() ) ) {
512 paint.save();
513 paint.setClipRegion( event->region().intersect(frameRect()) );
514 drawFrame( &paint );
515 paint.restore();
516 }
517 if ( event->rect().intersects( contentsRect() ) &&
518 (fstyle & MShape) != HLine && (fstyle & MShape) != VLine ) {
519 paint.setClipRegion( event->region().intersect( contentsRect() ) );
520 drawContents( &paint );
521 }
522}
523
524
525/*!
526 Processes the resize event \a e.
527
528 Adjusts the frame rectangle for the resized widget. The frame
529 rectangle is elastic, and the surrounding area is static.
530
531 The resulting frame rectangle may be null or invalid. You can use
532 setMinimumSize() to avoid those possibilities.
533
534 Nothing is done if the frame rectangle is a \link QRect::isNull()
535 null rectangle\endlink already.
536*/
537
538void QFrame::resizeEvent( QResizeEvent *e )
539{
540 if ( !frect.isNull() ) {
541 QRect r( frect.x(), frect.y(),
542 width() - (e->oldSize().width() - frect.width()),
543 height() - (e->oldSize().height() - frect.height()) );
544 setFrameRect( r );
545 }
546 QWidget::resizeEvent( e );
547}
548
549
550/*!
551 Draws the frame using the painter \a p and the current frame
552 attributes and color group. The rectangle inside the frame is not
553 affected.
554
555 This function is virtual, but in general you do not need to
556 reimplement it. If you do, note that the QPainter is already open
557 and must remain open.
558
559 \sa frameRect(), contentsRect(), drawContents(), frameStyle(), setPalette()
560*/
561
562void QFrame::drawFrame( QPainter *p )
563{
564 QPoint p1, p2;
565 QRect r = frameRect();
566 int type = fstyle & MShape;
567 int cstyle = fstyle & MShadow;
568#ifdef QT_NO_DRAWUTIL
569 p->setPen( black ); // ####
570 p->drawRect( r ); //### a bit too simple
571#else
572 const QColorGroup & g = colorGroup();
573
574#ifndef QT_NO_STYLE
575 QStyleOption opt(lineWidth(),midLineWidth());
576
577 QStyle::SFlags flags = QStyle::Style_Default;
578 if (isEnabled())
579 flags |= QStyle::Style_Enabled;
580 if (cstyle == Sunken)
581 flags |= QStyle::Style_Sunken;
582 else if (cstyle == Raised)
583 flags |= QStyle::Style_Raised;
584 if (hasFocus())
585 flags |= QStyle::Style_HasFocus;
586 if (hasMouse())
587 flags |= QStyle::Style_MouseOver;
588#endif // QT_NO_STYLE
589
590 switch ( type ) {
591
592 case Box:
593 if ( cstyle == Plain )
594 qDrawPlainRect( p, r, g.foreground(), lwidth );
595 else
596 qDrawShadeRect( p, r, g, cstyle == Sunken, lwidth,
597 midLineWidth() );
598 break;
599
600 case LineEditPanel:
601 style().drawPrimitive( QStyle::PE_PanelLineEdit, p, r, g, flags, opt );
602 break;
603
604 case GroupBoxPanel:
605 style().drawPrimitive( QStyle::PE_PanelGroupBox, p, r, g, flags, opt );
606 break;
607
608 case TabWidgetPanel:
609 style().drawPrimitive( QStyle::PE_PanelTabWidget, p, r, g, flags, opt );
610 break;
611
612 case MenuBarPanel:
613#ifndef QT_NO_STYLE
614 style().drawPrimitive(QStyle::PE_PanelMenuBar, p, r, g, flags, opt);
615 break;
616#endif // fall through to Panel if QT_NO_STYLE
617
618 case ToolBarPanel:
619#ifndef QT_NO_STYLE
620 style().drawPrimitive( QStyle::PE_PanelDockWindow, p, rect(), g, flags, opt);
621 break;
622#endif // fall through to Panel if QT_NO_STYLE
623
624 case StyledPanel:
625#ifndef QT_NO_STYLE
626 if ( cstyle == Plain )
627 qDrawPlainRect( p, r, g.foreground(), lwidth );
628 else
629 style().drawPrimitive(QStyle::PE_Panel, p, r, g, flags, opt);
630 break;
631#endif // fall through to Panel if QT_NO_STYLE
632
633 case PopupPanel:
634#ifndef QT_NO_STYLE
635 {
636 int vextra = style().pixelMetric(QStyle::PM_PopupMenuFrameVerticalExtra, this),
637 hextra = style().pixelMetric(QStyle::PM_PopupMenuFrameHorizontalExtra, this);
638 if(vextra > 0 || hextra > 0) {
639 QRect fr = frameRect();
640 int fw = frameWidth();
641 if(vextra > 0) {
642 style().drawControl(QStyle::CE_PopupMenuVerticalExtra, p, this,
643 QRect(fr.x() + fw, fr.y() + fw, fr.width() - (fw*2), vextra),
644 g, flags, opt);
645 style().drawControl(QStyle::CE_PopupMenuVerticalExtra, p, this,
646 QRect(fr.x() + fw, fr.bottom() - fw - vextra, fr.width() - (fw*2), vextra),
647 g, flags, opt);
648 }
649 if(hextra > 0) {
650 style().drawControl(QStyle::CE_PopupMenuHorizontalExtra, p, this,
651 QRect(fr.x() + fw, fr.y() + fw + vextra, hextra, fr.height() - (fw*2) - vextra),
652 g, flags, opt);
653 style().drawControl(QStyle::CE_PopupMenuHorizontalExtra, p, this,
654 QRect(fr.right() - fw - hextra, fr.y() + fw + vextra, hextra, fr.height() - (fw*2) - vextra),
655 g, flags, opt);
656 }
657 }
658
659 if ( cstyle == Plain )
660 qDrawPlainRect( p, r, g.foreground(), lwidth );
661 else
662 style().drawPrimitive(QStyle::PE_PanelPopup, p, r, g, flags, opt);
663 break;
664 }
665#endif // fall through to Panel if QT_NO_STYLE
666
667 case Panel:
668 if ( cstyle == Plain )
669 qDrawPlainRect( p, r, g.foreground(), lwidth );
670 else
671 qDrawShadePanel( p, r, g, cstyle == Sunken, lwidth );
672 break;
673
674 case WinPanel:
675 if ( cstyle == Plain )
676 qDrawPlainRect( p, r, g.foreground(), wpwidth );
677 else
678 qDrawWinPanel( p, r, g, cstyle == Sunken );
679 break;
680 case HLine:
681 case VLine:
682 if ( type == HLine ) {
683 p1 = QPoint( r.x(), r.height()/2 );
684 p2 = QPoint( r.x()+r.width(), p1.y() );
685 }
686 else {
687 p1 = QPoint( r.x()+r.width()/2, 0 );
688 p2 = QPoint( p1.x(), r.height() );
689 }
690 if ( cstyle == Plain ) {
691 QPen oldPen = p->pen();
692 p->setPen( QPen(g.foreground(),lwidth) );
693 p->drawLine( p1, p2 );
694 p->setPen( oldPen );
695 }
696 else
697 qDrawShadeLine( p, p1, p2, g, cstyle == Sunken,
698 lwidth, midLineWidth() );
699 break;
700 }
701#endif // QT_NO_DRAWUTIL
702}
703
704
705/*!
706 Virtual function that draws the contents of the frame.
707
708 The QPainter is already open when you get it, and you must leave
709 it open. Painter \link QPainter::setWorldMatrix()
710 transformations\endlink are switched off on entry. If you
711 transform the painter, remember to take the frame into account and
712 \link QPainter::resetXForm() reset transformation\endlink before
713 returning.
714
715 This function is reimplemented by subclasses that draw something
716 inside the frame. It should only draw inside contentsRect(). The
717 default function does nothing.
718
719 \sa contentsRect(), QPainter::setClipRect()
720*/
721
722void QFrame::drawContents( QPainter * )
723{
724}
725
726
727/*!
728 Virtual function that is called when the frame style, line width
729 or mid-line width changes.
730
731 This function can be reimplemented by subclasses that need to know
732 when the frame attributes change.
733
734 The default implementation calls update().
735*/
736
737void QFrame::frameChanged()
738{
739 update();
740 updateGeometry();
741}
742
743/*!\reimp
744 */
745void QFrame::styleChange( QStyle& old )
746{
747 updateFrameWidth( TRUE );
748 QWidget::styleChange( old );
749}
750
751#endif //QT_NO_FRAME
Note: See TracBrowser for help on using the repository browser.