diff options
author | Benjamin Poulain <benjamin.poulain@nokia.com> | 2009-08-14 08:04:36 (GMT) |
---|---|---|
committer | Benjamin Poulain <benjamin.poulain@nokia.com> | 2009-08-14 08:04:36 (GMT) |
commit | 0fd4ecf10bf57d56cd50f3bd6aeff5af381cef26 (patch) | |
tree | 5946b6811fba5ab0939c1ffc59ba9897de7be9c3 | |
parent | e58f3d36fba82f69debe5a37ab8e25eac1dddbcf (diff) | |
download | Qt-0fd4ecf10bf57d56cd50f3bd6aeff5af381cef26.zip Qt-0fd4ecf10bf57d56cd50f3bd6aeff5af381cef26.tar.gz Qt-0fd4ecf10bf57d56cd50f3bd6aeff5af381cef26.tar.bz2 |
Fix the painting of QComboBox on Mac when the rect is not at the origin
The style was assuming that the combo box is painted at (0,0). This is
not the case when the painting is done in the delegate of an item view.
The offset of the rect is now taken into account to paint the style.
HIRect has been replaced by QRect when it make sense.
Task-number: 00026815
Reviewed-by: Richard Moe Gustavsen
-rw-r--r-- | src/gui/styles/qmacstyle_mac.mm | 102 | ||||
-rw-r--r-- | tests/auto/qcombobox/tst_qcombobox.cpp | 44 |
2 files changed, 104 insertions, 42 deletions
diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm index de81fa8..82e0b34 100644 --- a/src/gui/styles/qmacstyle_mac.mm +++ b/src/gui/styles/qmacstyle_mac.mm @@ -488,7 +488,7 @@ public: inline int animateSpeed(Animates) const { return 33; } // Utility functions - void drawColorlessButton(const HIRect &macRect, HIThemeButtonDrawInfo *bdi, + void drawColorlessButton(const QRect &macRect, HIThemeButtonDrawInfo *bdi, QPainter *p, const QStyleOption *opt) const; void drawPantherTab(const QStyleOptionTab *tab, QPainter *p, const QWidget *w = 0) const; @@ -505,7 +505,7 @@ public: static QRect comboboxEditBounds(const QRect &outerBounds, const HIThemeButtonDrawInfo &bdi); - static void drawCombobox(const HIRect &outerBounds, const HIThemeButtonDrawInfo &bdi, QPainter *p); + static void drawCombobox(const QRect &outerBounds, const HIThemeButtonDrawInfo &bdi, QPainter *p); static void drawTableHeader(const HIRect &outerBounds, bool drawTopBorder, bool drawLeftBorder, const HIThemeButtonDrawInfo &bdi, QPainter *p); bool contentFitsInPushButton(const QStyleOptionButton *btn, HIThemeButtonDrawInfo *bdi, @@ -1287,11 +1287,12 @@ QRect QMacStylePrivate::comboboxEditBounds(const QRect &outerBounds, const HIThe create it manually by drawing a small Carbon combo onto a pixmap (use pixmap cache), chop it up, and copy it back onto the widget. Othervise, draw the combobox supplied by Carbon directly. */ -void QMacStylePrivate::drawCombobox(const HIRect &outerBounds, const HIThemeButtonDrawInfo &bdi, QPainter *p) +void QMacStylePrivate::drawCombobox(const QRect &outerBounds, const HIThemeButtonDrawInfo &bdi, QPainter *p) { - if (!(bdi.kind == kThemeComboBox && outerBounds.size.height > 28)){ + if (!(bdi.kind == kThemeComboBox && outerBounds.height() > 28)){ // We have an unscaled combobox, or popup-button; use Carbon directly. - HIRect innerBounds = QMacStylePrivate::comboboxInnerBounds(outerBounds, bdi.kind); + const HIRect hiOuterBounds = qt_hirectForQRect(outerBounds); + HIRect innerBounds = QMacStylePrivate::comboboxInnerBounds(hiOuterBounds, bdi.kind); HIThemeDrawButton(&innerBounds, &bdi, QMacCGContext(p), kHIThemeOrientationNormal, 0); } else { QPixmap buffer; @@ -1306,31 +1307,50 @@ void QMacStylePrivate::drawCombobox(const HIRect &outerBounds, const HIThemeButt QPixmapCache::insert(key, buffer); } - const int bwidth = 20; - const int fwidth = 10; - const int fheight = 10; - int w = qRound(outerBounds.size.width); - int h = qRound(outerBounds.size.height); - int bstart = w - bwidth; - int blower = fheight + 1; - int flower = h - fheight; - int sheight = flower - fheight; - int center = qRound(outerBounds.size.height + outerBounds.origin.y) / 2; + const int widgetX = outerBounds.x(); + const int widgetY = outerBounds.y(); + const int widgetWidth = outerBounds.width(); + const int widgetHeight = outerBounds.height(); + + const int buttonWidth = 20; + const int frameWidth = 10; + const int frameHeight = 10; // frame height + const int bstart = widgetWidth - buttonWidth; + const int flower = widgetHeight - frameHeight; // Draw upper and lower gap - p->drawPixmap(fwidth, 0, bstart - fwidth, fheight, buffer, fwidth, 0, 1, fheight); - p->drawPixmap(fwidth, flower, bstart - fwidth, fheight, buffer, fwidth, buffer.height() - fheight, 1, fheight); + p->drawPixmap(widgetX + frameWidth, widgetY, bstart - frameWidth, frameHeight, + buffer, frameWidth, 0, 1, frameHeight); // upper + p->drawPixmap(widgetX + frameWidth, widgetY + flower, bstart - frameWidth, frameHeight, + buffer, frameWidth, buffer.height() - frameHeight, 1, frameHeight); // lower + + const int center = widgetY + widgetHeight / 2; + const int sheight = flower - frameHeight; + // Draw left and right gap. Right gap is drawn top and bottom separatly - p->drawPixmap(0, fheight, fwidth, sheight, buffer, 0, fheight, fwidth, 1); - p->drawPixmap(bstart, fheight, bwidth, center - fheight, buffer, buffer.width() - bwidth, fheight - 1, bwidth, 1); - p->drawPixmap(bstart, center, bwidth, sheight / 2, buffer, buffer.width() - bwidth, fheight + 6, bwidth, 1); + p->drawPixmap(widgetX, widgetY + frameHeight, frameWidth, sheight, + buffer, 0, frameHeight, frameWidth, 1); // right + p->drawPixmap(widgetX + bstart, widgetY + frameHeight, buttonWidth, widgetHeight / 2 - frameHeight, + buffer, buffer.width() - buttonWidth, frameHeight - 1, buttonWidth, 1); // top left + p->drawPixmap(widgetX + bstart, center, buttonWidth, sheight / 2, + buffer, buffer.width() - buttonWidth, frameHeight + 6, buttonWidth, 1); // bottom left + // Draw arrow - p->drawPixmap(bstart, center - 4, bwidth - 3, 6, buffer, buffer.width() - bwidth, fheight, bwidth - 3, 6); + p->drawPixmap(widgetX + bstart, center - 4, buttonWidth - 3, 6, + buffer, buffer.width() - buttonWidth, frameHeight, buttonWidth - 3, 6); + // Draw corners - p->drawPixmap(0, 0, fwidth, fheight, buffer, 0, 0, fwidth, fheight); - p->drawPixmap(bstart, 0, bwidth, fheight, buffer, buffer.width() - bwidth, 0, bwidth, fheight); - p->drawPixmap(0, flower, fwidth, fheight, buffer, 0, buffer.height() - fheight, fwidth, fheight); - p->drawPixmap(bstart, h - blower, bwidth, blower, buffer, buffer.width() - bwidth, buffer.height() - blower, bwidth, blower); + p->drawPixmap(widgetX, widgetY, frameWidth, frameHeight, + buffer, 0, 0, frameWidth, frameHeight); // top left + p->drawPixmap(widgetX + bstart, widgetY, buttonWidth, frameHeight, + buffer, buffer.width() - buttonWidth, 0, buttonWidth, frameHeight); // top right + p->drawPixmap(widgetX, widgetY + flower, frameWidth, frameHeight, + buffer, 0, buffer.height() - frameHeight, frameWidth, frameHeight); // bottom left + + const int blower = frameHeight + 1; + p->drawPixmap(widgetX + bstart, widgetY + widgetHeight - blower, buttonWidth, blower, + buffer, + buffer.width() - buttonWidth, buffer.height() - blower, buttonWidth, blower); // bottom right } } @@ -1895,7 +1915,7 @@ bool QMacStylePrivate::doAnimate(QMacStylePrivate::Animates as) return true; } -void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonDrawInfo *bdi, +void QMacStylePrivate::drawColorlessButton(const QRect &outerBounds, HIThemeButtonDrawInfo *bdi, QPainter *p, const QStyleOption *opt) const { int xoff = 0, @@ -1905,8 +1925,8 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD finalyoff = 0; const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt); - int width = int(macRect.size.width) + extraWidth; - int height = int(macRect.size.height) + extraHeight; + const int width = outerBounds.width() + extraWidth; + const int height = outerBounds.height() + extraHeight; if (width <= 0 || height <= 0) return; // nothing to draw @@ -1923,11 +1943,11 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD // Carbon combos don't scale. Therefore we draw it // ourselves, if a scaled version is needed. QPainter tmpPainter(&activePixmap); - QMacStylePrivate::drawCombobox(macRect, *bdi, &tmpPainter); + QMacStylePrivate::drawCombobox(outerBounds, *bdi, &tmpPainter); } else { QMacCGContext cg(&activePixmap); - HIRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height); + HIRect newRect = CGRectMake(xoff, yoff, outerBounds.width(), outerBounds.height()); HIThemeDrawButton(&newRect, bdi, cg, kHIThemeOrientationNormal, 0); } } @@ -1967,7 +1987,7 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD colorlessPixmap.fill(Qt::transparent); QMacCGContext cg(&colorlessPixmap); - HIRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height); + HIRect newRect = CGRectMake(xoff, yoff, outerBounds.width(), outerBounds.height()); int oldValue = bdi->value; bdi->value = kThemeButtonOff; HIThemeDrawButton(&newRect, bdi, cg, kHIThemeOrientationNormal, 0); @@ -1997,7 +2017,7 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD } QPixmapCache::insert(key, pm); } - p->drawPixmap(int(macRect.origin.x), int(macRect.origin.y) + finalyoff, width, height, pm); + p->drawPixmap(outerBounds.x(), outerBounds.y() + finalyoff, width, height, pm); } QMacStyle::QMacStyle() @@ -3221,15 +3241,13 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai bdi.value = kThemeButtonOn; else bdi.value = kThemeButtonOff; - HIRect macRect; - if (pe == PE_Q3CheckListExclusiveIndicator || pe == PE_Q3CheckListIndicator) - macRect = qt_hirectForQRect(opt->rect); - else - macRect = qt_hirectForQRect(opt->rect); - if (!drawColorless) + + if (!drawColorless) { + const HIRect macRect = qt_hirectForQRect(opt->rect); HIThemeDrawButton(&macRect, &bdi, cg, kHIThemeOrientationNormal, 0); - else - d->drawColorlessButton(macRect, &bdi, p, opt); + } else { + d->drawColorlessButton(opt->rect, &bdi, p, opt); + } break; } case PE_FrameFocusRect: // Use the our own focus widget stuff. @@ -4945,9 +4963,9 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex d->initComboboxBdi(combo, &bdi, widget, d->getDrawState(opt->state)); bool drawColorless = combo->palette.currentColorGroup() == QPalette::Active && tds == kThemeStateInactive; if (!drawColorless) - QMacStylePrivate::drawCombobox(qt_hirectForQRect(combo->rect), bdi, p); + QMacStylePrivate::drawCombobox(combo->rect, bdi, p); else - d->drawColorlessButton(qt_hirectForQRect(combo->rect), &bdi, p, opt); + d->drawColorlessButton(combo->rect, &bdi, p, opt); } break; case CC_TitleBar: diff --git a/tests/auto/qcombobox/tst_qcombobox.cpp b/tests/auto/qcombobox/tst_qcombobox.cpp index b7a66af..204a2fa 100644 --- a/tests/auto/qcombobox/tst_qcombobox.cpp +++ b/tests/auto/qcombobox/tst_qcombobox.cpp @@ -144,6 +144,7 @@ private slots: void noScrollbar(); void setItemDelegate(); void task253944_itemDelegateIsReset(); + void paintingWithOffset(); protected slots: void onEditTextChanged( const QString &newString ); @@ -2232,5 +2233,48 @@ void tst_QComboBox::task253944_itemDelegateIsReset() QCOMPARE(comboBox.itemDelegate(), itemDelegate); } +static void paintCombo(QImage *image, const QRect &rect) +{ + class FriendlyCombo : public QComboBox { + public: + void styleOption(QStyleOptionComboBox *optCombo) { + initStyleOption(optCombo); + } + } combo; + combo.setEditable(true); + + QStyleOptionComboBox optCombo; + combo.styleOption(&optCombo); + optCombo.rect = rect; + optCombo.palette.setCurrentColorGroup(QPalette::Active); + optCombo.state = QStyle::State_None; + + QPainter painter(image); + painter.fillRect(image->rect(), Qt::white); + QApplication::style()->drawComplexControl(QStyle::CC_ComboBox, &optCombo, &painter, 0); +} + +void tst_QComboBox::paintingWithOffset() +{ + // The painting of the combobox should not depend on its position in + // the widget. Some style are making the assumuption that the combobox + // start at 0,0 + const QSize comboSize(80, 30); + QImage noOffsetImage(comboSize, QImage::Format_ARGB32); + const QRect noOffsetRect(QPoint(0, 0), comboSize); + paintCombo(&noOffsetImage, noOffsetRect); + + QImage offsetImage(105, 80, QImage::Format_ARGB32); + const QRect offsetRect(QPoint(25, 50), comboSize); + paintCombo(&offsetImage, offsetRect); + + QImage translatedOffsetImage(comboSize, QImage::Format_ARGB32); + { + QPainter painter(&translatedOffsetImage); + painter.drawImage(noOffsetRect, offsetImage, offsetRect); + } + QCOMPARE(noOffsetImage, translatedOffsetImage); +} + QTEST_MAIN(tst_QComboBox) #include "tst_qcombobox.moc" |