Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

qwt_push_button.cpp

00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** 00002 * Qwt Widget Library 00003 * Copyright (C) 1997 Josef Wilgen 00004 * Copyright (C) 2002 Uwe Rathmann 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the Qwt License, Version 1.0 00008 *****************************************************************************/ 00009 00010 // vim: expandtab 00011 00012 #include <qpainter.h> 00013 #include <qpicture.h> 00014 #include <qsimplerichtext.h> 00015 #include <qstylesheet.h> 00016 #include <qstyle.h> 00017 #include "qwt_text.h" 00018 #include "qwt_push_button.h" 00019 00020 #ifndef QT_NO_PICTURE 00021 00022 class QwtPBPaintFilter: public QPicture 00023 { 00024 // A helper class that filters the QPushButton paint commands 00025 // and changes them according the additional features of QwtPushButton 00026 00027 public: 00028 QwtPBPaintFilter(const QwtPushButton *); 00029 00030 protected: 00031 virtual bool cmd(int, QPainter *, QPDevCmdParam *); 00032 00033 private: 00034 bool isLabel(const QPixmap *) const; 00035 QRect indentRect(const QRect &) const; 00036 00037 const QwtPushButton *d_button; 00038 QRect d_iconRect; 00039 bool d_inFilter; 00040 }; 00041 00042 QwtPBPaintFilter::QwtPBPaintFilter(const QwtPushButton *button): 00043 d_button(button), 00044 d_inFilter(FALSE) 00045 { 00046 } 00047 00048 bool QwtPBPaintFilter::cmd(int c, QPainter *painter, QPDevCmdParam *param) 00049 { 00050 switch(c) 00051 { 00052 case PdcDrawTextFormatted: 00053 case PdcDrawText2Formatted: 00054 { 00055 Qt::TextFormat textFormat = d_button->usedTextFormat(); 00056 if ( textFormat == Qt::PlainText ) 00057 { 00058 param[1].ival = d_button->alignment(); 00059 00060 QRect &r = *((QRect *)param[0].rect); 00061 r = indentRect(r); 00062 00063 return QPicture::cmd(c, painter, param); 00064 } 00065 if ( textFormat == Qt::RichText ) 00066 { 00067 if ( !d_inFilter ) // avoid recursive calls 00068 { 00069 d_inFilter = TRUE; 00070 QwtRichText richText(*param[2].str, painter->font(), 00071 d_button->alignment(), painter->pen().color()); 00072 richText.draw(painter, indentRect(*param[0].rect)); 00073 d_inFilter = FALSE; 00074 return TRUE; 00075 } 00076 } 00077 break; 00078 } 00079 case PdcDrawPixmap: 00080 { 00081 if ( d_inFilter ) // avoid recursive calls 00082 { 00083 // There might be pixmaps embedded in rich text. 00084 // This problem is solved by the d_inFilter guard 00085 // above too. 00086 break; 00087 } 00088 00089 if ( isLabel(param[1].pixmap) && 00090 !(d_button->alignment() & Qt::AlignCenter)) 00091 { 00092 const QRect contentsRect = 00093 #if QT_VERSION >= 300 00094 d_button->style().subRect( 00095 QStyle::SR_PushButtonContents, d_button); 00096 #else 00097 d_button->style().pushButtonContentsRect( 00098 (QPushButton *)d_button); 00099 #endif 00100 00101 QRect pixRect = contentsRect; 00102 if ( !d_iconRect.isEmpty() ) 00103 pixRect.setX(d_iconRect.right()); 00104 00105 // Many styles move the label right/down 00106 // when the button is down. 00107 00108 #if QT_VERSION >= 300 00109 const QRect &r = *((QRect *)param[0].rect); 00110 #else 00111 const QRect r(*param[0].point, param[1].pixmap->size()); 00112 #endif 00113 const int offsetY = r.center().y() - pixRect.center().y(); 00114 const int offsetX = d_iconRect.isEmpty() ? offsetY : 0; 00115 pixRect.moveBy(offsetX, offsetY); 00116 00117 if ( d_button->indent() > 0 ) 00118 { 00119 const int indent = d_button->indent(); 00120 const int align = d_button->alignment(); 00121 00122 if ( align & Qt::AlignRight ) 00123 pixRect.setRight(pixRect.right() - indent); 00124 else if ( align & Qt::AlignLeft ) 00125 pixRect.setLeft(pixRect.left() + indent); 00126 00127 if ( align & Qt::AlignTop ) 00128 pixRect.setTop(pixRect.top() + indent); 00129 else if ( align & Qt::AlignBottom ) 00130 pixRect.setBottom(pixRect.bottom() - indent); 00131 } 00132 00133 pixRect &= contentsRect; // clip to contentsRect 00134 00135 d_inFilter = TRUE; 00136 00137 d_button->style().drawItem(painter, 00138 #if QT_VERSION >= 300 00139 pixRect, 00140 #else 00141 pixRect.x(), pixRect.y(), 00142 pixRect.width(), pixRect.height(), 00143 #endif 00144 d_button->alignment(), d_button->colorGroup(), 00145 d_button->isEnabled(), param[1].pixmap, QString::null); 00146 00147 d_inFilter = FALSE; 00148 return TRUE; 00149 } 00150 else 00151 { 00152 // We save the position of the icon. We need it later 00153 // to align the label pixmap. Hope that there are no styles 00154 // that paint the pixmap before the icon. 00155 #if QT_VERSION < 300 00156 d_iconRect = QRect(*param[0].point, param[1].pixmap->size()); 00157 #else 00158 d_iconRect = *param[0].rect; 00159 #endif 00160 } 00161 break; 00162 } 00163 } 00164 return QPicture::cmd(c, painter, param); 00165 } 00166 00167 QRect QwtPBPaintFilter::indentRect(const QRect &rect) const 00168 { 00169 const int indent = d_button->indent(); 00170 if ( indent <= 0 ) 00171 return rect; 00172 00173 QRect r = rect; 00174 if ( d_button->alignment() & Qt::AlignRight ) 00175 r.setRight(r.right() - indent); 00176 else if ( d_button->alignment() & Qt::AlignLeft ) 00177 r.setLeft(r.left() + indent); 00178 00179 if ( d_button->alignment() & Qt::AlignTop ) 00180 r.setTop(r.top() + indent); 00181 else if ( d_button->alignment() & Qt::AlignBottom ) 00182 r.setBottom(r.bottom() - indent); 00183 00184 return r; 00185 } 00186 00187 bool QwtPBPaintFilter::isLabel(const QPixmap *pixmap) const 00188 { 00189 if ( !d_button->pixmap() || 00190 d_button->pixmap()->serialNumber() != pixmap->serialNumber() ) 00191 { 00192 return FALSE; 00193 } 00194 00195 if ( d_button->iconSet() && !d_button->iconSet()->isNull() ) 00196 { 00197 if ( d_button->iconSet()->pixmap().serialNumber() == 00198 pixmap->serialNumber() ) 00199 { 00200 // Iconset and label are both set, and use the same pixmap. 00201 // We hope the iconSet is painted first. 00202 00203 static bool firstPixmap = TRUE; 00204 firstPixmap = !firstPixmap; 00205 00206 return !firstPixmap; 00207 } 00208 } 00209 return TRUE; 00210 } 00211 00212 #endif // !QT_NO_PICTURE 00213 00217 QwtPushButton::QwtPushButton(QWidget *parent, const char *name): 00218 QPushButton(parent, name) 00219 { 00220 init(); 00221 } 00222 00227 QwtPushButton::QwtPushButton(const QString &text, 00228 QWidget *parent, const char *name): 00229 QPushButton(text, parent, name) 00230 { 00231 init(); 00232 } 00233 00237 QwtPushButton::QwtPushButton(const QIconSet &iconSet, const QString &text, 00238 QWidget *parent, const char *name): 00239 QPushButton(iconSet, text, parent, name) 00240 { 00241 init(); 00242 } 00243 00245 void QwtPushButton::init() 00246 { 00247 d_textFormat = Qt::AutoText; 00248 d_alignment = Qt::AlignCenter | Qt::ExpandTabs | Qt::WordBreak; 00249 d_indent = 4; 00250 } 00251 00262 Qt::TextFormat QwtPushButton::usedTextFormat() const 00263 { 00264 #ifndef QT_NO_PICTURE 00265 if ( d_textFormat == Qt::AutoText && QStyleSheet::mightBeRichText(text()) ) 00266 return Qt::RichText; 00267 #endif 00268 00269 return Qt::PlainText; 00270 } 00271 00277 Qt::TextFormat QwtPushButton::textFormat() const 00278 { 00279 return d_textFormat; 00280 } 00281 00291 void QwtPushButton::setTextFormat(TextFormat textFormat) 00292 { 00293 d_textFormat = textFormat; 00294 } 00295 00301 int QwtPushButton::alignment() const 00302 { 00303 return d_alignment; 00304 } 00305 00315 void QwtPushButton::setAlignment(int alignment) 00316 { 00317 d_alignment = alignment; 00318 } 00319 00325 int QwtPushButton::indent() const 00326 { 00327 return d_indent; 00328 } 00329 00340 void QwtPushButton::setIndent(int indent) 00341 { 00342 d_indent = indent; 00343 } 00344 00352 int QwtPushButton::heightForWidth(int width) const 00353 { 00354 if ( pixmap() ) 00355 return QPushButton::heightForWidth(width); 00356 00357 QwtText *txt = QwtText::makeText(text(), usedTextFormat(), 00358 d_alignment, font()); 00359 00360 int h = sizeHint().height(); 00361 h -= txt->boundingRect().height(); 00362 h += txt->heightForWidth(width); 00363 00364 delete txt; 00365 00366 return h; 00367 } 00368 00370 QSize QwtPushButton::sizeHint() const 00371 { 00372 QSize hint = QPushButton::sizeHint(); 00373 00374 if ( d_indent > 0 ) 00375 { 00376 if ( (d_alignment & Qt::AlignLeft) 00377 || (d_alignment & Qt::AlignRight) ) 00378 { 00379 hint.setWidth(hint.width() + d_indent); 00380 } 00381 if ( (d_alignment & Qt::AlignTop) 00382 || (d_alignment & Qt::AlignBottom) ) 00383 { 00384 hint.setHeight(hint.height() + d_indent); 00385 } 00386 } 00387 00388 if ( pixmap() ) 00389 return hint; 00390 00391 const Qt::TextFormat textFormat = usedTextFormat(); 00392 if ( textFormat == Qt::RichText ) 00393 { 00394 QwtRichText richText(text(), font(), d_alignment); 00395 00396 const QSize sizeText = fontMetrics().size(Qt::ShowPrefix, text()); 00397 const QSize sizeRichText(richText.boundingRect().size()); 00398 00399 int iconHeight = 0; 00400 if ( iconSet() && !iconSet()->isNull() ) 00401 { 00402 iconHeight = iconSet()->pixmap(QIconSet::Small, 00403 QIconSet::Normal).height(); 00404 } 00405 00406 const int heightText = QMAX(iconHeight, sizeText.height()); 00407 const int heightRichText = QMAX(iconHeight, sizeRichText.height()); 00408 00409 hint.setWidth(hint.width() - sizeText.width() + sizeRichText.width()); 00410 hint.setHeight(hint.height() - heightText + heightRichText); 00411 } 00412 00413 return hint; 00414 } 00415 00417 void QwtPushButton::drawButtonLabel(QPainter *painter) 00418 { 00419 #ifndef QT_NO_PICTURE 00420 // Unfortunately QStyle doesnīt offer an API to add 00421 // the alignment and rich text features. But we donīt want 00422 // to paint the button label on our own, as we would lose 00423 // the flexibility of the styles. So we let the style 00424 // paint the button label to a QPicture first, change 00425 // the paint commands and replay the manipulated commands 00426 // to the button. 00427 00428 QwtPBPaintFilter paintFilter(this); 00429 00430 QPainter picPainter(&paintFilter); 00431 picPainter.setFont(painter->font()); 00432 00433 #if QT_VERSION >= 300 00434 // When painting to QPicture the dotted line of the focus rect is 00435 // set to solid. ( 06.08.2003 ) 00436 // So we donīt set the Style_HasFocus flag and paint the focus rect 00437 // later directly to the button. 00438 00439 QStyle::SFlags flags = QStyle::Style_Default; 00440 if (isEnabled()) 00441 flags |= QStyle::Style_Enabled; 00442 if (isDown()) 00443 flags |= QStyle::Style_Down; 00444 if (isOn()) 00445 flags |= QStyle::Style_On; 00446 if (! isFlat() && ! isDown()) 00447 flags |= QStyle::Style_Raised; 00448 if (isDefault()) 00449 flags |= QStyle::Style_ButtonDefault; 00450 00451 style().drawControl(QStyle::CE_PushButtonLabel, &picPainter, this, 00452 style().subRect(QStyle::SR_PushButtonContents, this), 00453 colorGroup(), flags); 00454 #else 00455 // For Qt <= 2.x the focus rect is not painted in 00456 // drawButtonLabel. So we donīt need a workaround here. 00457 00458 QPushButton::drawButtonLabel(&picPainter); 00459 #endif 00460 00461 picPainter.end(); 00462 00463 paintFilter.play(painter); 00464 00465 #if QT_VERSION >= 300 00466 if (hasFocus()) 00467 { 00468 // Paint the focus rect on top of the button label. 00469 00470 flags |= QStyle::Style_HasFocus; 00471 style().drawPrimitive(QStyle::PE_FocusRect, painter, 00472 style().subRect(QStyle::SR_PushButtonFocusRect, this), 00473 colorGroup(), flags); 00474 } 00475 #endif 00476 00477 #else // QT_NO_PICTURE 00478 QPushButton::drawButtonLabel(painter); 00479 #endif 00480 } 00481 00482 // Local Variables: 00483 // mode: C++ 00484 // c-file-style: "stroustrup" 00485 // indent-tabs-mode: nil 00486 // End:

Generated on Tue Nov 16 21:12:21 2004 for Qwt User's Guide by doxygen 1.3.8