diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-12-17 18:05:15 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-12-17 18:05:15 -0800 |
commit | 1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353 (patch) | |
tree | 4457a7306ea5acb43fe05bfe0973b1f7faf97ba2 /WebCore/platform/qt/RenderThemeQt.cpp | |
parent | 9364f22aed35e1a1e9d07c121510f80be3ab0502 (diff) | |
download | external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.zip external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.gz external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.bz2 |
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'WebCore/platform/qt/RenderThemeQt.cpp')
-rw-r--r-- | WebCore/platform/qt/RenderThemeQt.cpp | 773 |
1 files changed, 561 insertions, 212 deletions
diff --git a/WebCore/platform/qt/RenderThemeQt.cpp b/WebCore/platform/qt/RenderThemeQt.cpp index dbf080f..2a33e45 100644 --- a/WebCore/platform/qt/RenderThemeQt.cpp +++ b/WebCore/platform/qt/RenderThemeQt.cpp @@ -1,6 +1,8 @@ /* * This file is part of the WebKit project. * + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * * Copyright (C) 2006 Zack Rusin <zack@kde.org> * 2006 Dirk Mueller <mueller@kde.org> * 2006 Nikolas Zimmermann <zimmermann@kde.org> @@ -34,21 +36,71 @@ #include <QApplication> #include <QColor> #include <QDebug> -#include <QStyle> +#include <QFile> #include <QWidget> #include <QPainter> +#include <QPushButton> +#include <QStyleFactory> #include <QStyleOptionButton> #include <QStyleOptionFrameV2> #include "Color.h" +#include "CSSStyleSheet.h" #include "Document.h" #include "Page.h" #include "Font.h" #include "RenderTheme.h" #include "GraphicsContext.h" +#include "HTMLMediaElement.h" +#include "HTMLNames.h" namespace WebCore { +using namespace HTMLNames; + + +StylePainter::StylePainter(const RenderObject::PaintInfo& paintInfo) +{ + init(paintInfo.context ? paintInfo.context : 0); +} + +StylePainter::StylePainter(GraphicsContext* context) +{ + init(context); +} + +void StylePainter::init(GraphicsContext* context) +{ + painter = static_cast<QPainter*>(context->platformContext()); + widget = 0; + QPaintDevice* dev = 0; + if (painter) + dev = painter->device(); + if (dev && dev->devType() == QInternal::Widget) + widget = static_cast<QWidget*>(dev); + style = (widget ? widget->style() : QApplication::style()); + + if (painter) { + // the styles often assume being called with a pristine painter where no brush is set, + // so reset it manually + oldBrush = painter->brush(); + painter->setBrush(Qt::NoBrush); + + // painting the widget with anti-aliasing will make it blurry + // disable it here and restore it later + oldAntialiasing = painter->testRenderHint(QPainter::Antialiasing); + painter->setRenderHint(QPainter::Antialiasing, false); + } +} + +StylePainter::~StylePainter() +{ + if (painter) { + painter->setBrush(oldBrush); + painter->setRenderHints(QPainter::Antialiasing, oldAntialiasing); + } +} + RenderTheme* theme() { static RenderThemeQt rt; @@ -58,6 +110,33 @@ RenderTheme* theme() RenderThemeQt::RenderThemeQt() : RenderTheme() { + QPushButton button; + button.setAttribute(Qt::WA_MacSmallSize); + QFont defaultButtonFont = QApplication::font(&button); + QFontInfo fontInfo(defaultButtonFont); + m_buttonFontFamily = defaultButtonFont.family(); +#ifdef Q_WS_MAC + m_buttonFontPixelSize = fontInfo.pixelSize(); +#endif + + m_fallbackStyle = 0; +} + +RenderThemeQt::~RenderThemeQt() +{ + delete m_fallbackStyle; +} + +// for some widget painting, we need to fallback to Windows style +QStyle* RenderThemeQt::fallbackStyle() +{ + if(!m_fallbackStyle) + m_fallbackStyle = QStyleFactory::create(QLatin1String("windows")); + + if(!m_fallbackStyle) + m_fallbackStyle = QApplication::style(); + + return m_fallbackStyle; } bool RenderThemeQt::supportsHover(const RenderStyle*) const @@ -67,13 +146,13 @@ bool RenderThemeQt::supportsHover(const RenderStyle*) const bool RenderThemeQt::supportsFocusRing(const RenderStyle* style) const { - return supportsFocus(style->appearance()); + return true; // Qt provides this through the style } -short RenderThemeQt::baselinePosition(const RenderObject* o) const +int RenderThemeQt::baselinePosition(const RenderObject* o) const { - if (o->style()->appearance() == CheckboxAppearance || - o->style()->appearance() == RadioAppearance) + if (o->style()->appearance() == CheckboxPart || + o->style()->appearance() == RadioPart) return o->marginTop() + o->height() - 2; // Same as in old khtml return RenderTheme::baselinePosition(o); } @@ -84,7 +163,7 @@ bool RenderThemeQt::controlSupportsTints(const RenderObject* o) const return false; // Checkboxes only have tint when checked. - if (o->style()->appearance() == CheckboxAppearance) + if (o->style()->appearance() == CheckboxPart) return isChecked(o); // For now assume other controls have tint if enabled. @@ -96,20 +175,42 @@ bool RenderThemeQt::supportsControlTints() const return true; } +static QRect inflateButtonRect(const QRect& originalRect) +{ + QStyleOptionButton option; + option.state |= QStyle::State_Small; + option.rect = originalRect; + + QRect layoutRect = QApplication::style()->subElementRect(QStyle::SE_PushButtonLayoutItem, + &option, 0); + if (!layoutRect.isNull()) { + int paddingLeft = layoutRect.left() - originalRect.left(); + int paddingRight = originalRect.right() - layoutRect.right(); + int paddingTop = layoutRect.top() - originalRect.top(); + int paddingBottom = originalRect.bottom() - layoutRect.bottom(); + + return originalRect.adjusted(-paddingLeft, -paddingTop, paddingRight, paddingBottom); + } else { + return originalRect; + } +} + void RenderThemeQt::adjustRepaintRect(const RenderObject* o, IntRect& r) { switch (o->style()->appearance()) { - case CheckboxAppearance: { + case CheckboxPart: { break; } - case RadioAppearance: { + case RadioPart: { break; } - case PushButtonAppearance: - case ButtonAppearance: { + case PushButtonPart: + case ButtonPart: { + QRect inflatedRect = inflateButtonRect(r); + r = IntRect(inflatedRect.x(), inflatedRect.y(), inflatedRect.width(), inflatedRect.height()); break; } - case MenulistAppearance: { + case MenulistPart: { break; } default: @@ -118,19 +219,17 @@ void RenderThemeQt::adjustRepaintRect(const RenderObject* o, IntRect& r) } bool RenderThemeQt::isControlStyled(const RenderStyle* style, const BorderData& border, - const BackgroundLayer& background, const Color& backgroundColor) const + const FillLayer& background, const Color& backgroundColor) const { - if (style->appearance() == TextFieldAppearance || style->appearance() == TextAreaAppearance) + if (style->appearance() == TextFieldPart + || style->appearance() == TextAreaPart + || style->appearance() == ListboxPart) { return style->border() != border; + } return RenderTheme::isControlStyled(style, border, background, backgroundColor); } -void RenderThemeQt::paintResizeControl(GraphicsContext*, const IntRect&) -{ -} - - Color RenderThemeQt::platformActiveSelectionBackgroundColor() const { QPalette pal = QApplication::palette(); @@ -166,43 +265,111 @@ int RenderThemeQt::minimumMenuListSize(RenderStyle*) const return 7 * fm.width(QLatin1Char('x')); } -void RenderThemeQt::adjustSliderThumbSize(RenderObject* o) const +static void computeSizeBasedOnStyle(RenderStyle* renderStyle) { - RenderTheme::adjustSliderThumbSize(o); -} + // If the width and height are both specified, then we have nothing to do. + if (!renderStyle->width().isIntrinsicOrAuto() && !renderStyle->height().isAuto()) + return; -bool RenderThemeQt::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) -{ - return paintButton(o, i, r); + QSize size(0, 0); + const QFontMetrics fm(renderStyle->font().font()); + QStyle* applicationStyle = QApplication::style(); + + switch (renderStyle->appearance()) { + case CheckboxPart: { + QStyleOption styleOption; + styleOption.state |= QStyle::State_Small; + int checkBoxWidth = applicationStyle->pixelMetric(QStyle::PM_IndicatorWidth, + &styleOption); + size = QSize(checkBoxWidth, checkBoxWidth); + break; + } + case RadioPart: { + QStyleOption styleOption; + styleOption.state |= QStyle::State_Small; + int radioWidth = applicationStyle->pixelMetric(QStyle::PM_ExclusiveIndicatorWidth, + &styleOption); + size = QSize(radioWidth, radioWidth); + break; + } + case PushButtonPart: + case ButtonPart: { + QStyleOptionButton styleOption; + styleOption.state |= QStyle::State_Small; + QSize contentSize = fm.size(Qt::TextShowMnemonic, QString::fromLatin1("X")); + QSize pushButtonSize = applicationStyle->sizeFromContents(QStyle::CT_PushButton, + &styleOption, + contentSize, + 0); + styleOption.rect = QRect(0, 0, pushButtonSize.width(), pushButtonSize.height()); + QRect layoutRect = applicationStyle->subElementRect(QStyle::SE_PushButtonLayoutItem, + &styleOption, + 0); + // If the style supports layout rects we use that, and + // compensate accordingly in paintButton() below. + if (!layoutRect.isNull()) { + size.setHeight(layoutRect.height()); + } else { + size.setHeight(pushButtonSize.height()); + } + + break; + } + case MenulistPart: { + QStyleOptionComboBox styleOption; + styleOption.state |= QStyle::State_Small; + int contentHeight = qMax(fm.lineSpacing(), 14) + 2; + QSize menuListSize = applicationStyle->sizeFromContents(QStyle::CT_ComboBox, + &styleOption, + QSize(0, contentHeight), + 0); + size.setHeight(menuListSize.height()); + break; + } + case TextFieldPart: { + const int verticalMargin = 1; + const int horizontalMargin = 2; + int h = qMax(fm.lineSpacing(), 14) + 2*verticalMargin; + int w = fm.width(QLatin1Char('x')) * 17 + 2*horizontalMargin; + QStyleOptionFrameV2 opt; + opt.lineWidth = applicationStyle->pixelMetric(QStyle::PM_DefaultFrameWidth, + &opt, 0); + QSize sz = applicationStyle->sizeFromContents(QStyle::CT_LineEdit, + &opt, + QSize(w, h).expandedTo(QApplication::globalStrut()), + 0); + size.setHeight(sz.height()); + break; + } + default: + break; + } + + // FIXME: Check is flawed, since it doesn't take min-width/max-width into account. + if (renderStyle->width().isIntrinsicOrAuto() && size.width() > 0) + renderStyle->setWidth(Length(size.width(), Fixed)); + if (renderStyle->height().isAuto() && size.height() > 0) + renderStyle->setHeight(Length(size.height(), Fixed)); } void RenderThemeQt::setCheckboxSize(RenderStyle* style) const { - // If the width and height are both specified, then we have nothing to do. - if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) - return; - - // FIXME: A hard-coded size of 13 is used. This is wrong but necessary for now. It matches Firefox. - // At different DPI settings on Windows, querying the theme gives you a larger size that accounts for - // the higher DPI. Until our entire engine honors a DPI setting other than 96, we can't rely on the theme's - // metrics. - const int ff = 13; - if (style->width().isIntrinsicOrAuto()) - style->setWidth(Length(ff, Fixed)); - - if (style->height().isAuto()) - style->setHeight(Length(ff, Fixed)); + computeSizeBasedOnStyle(style); } -bool RenderThemeQt::paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) +bool RenderThemeQt::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) { return paintButton(o, i, r); } void RenderThemeQt::setRadioSize(RenderStyle* style) const { - // This is the same as checkboxes. - setCheckboxSize(style); + computeSizeBasedOnStyle(style); +} + +bool RenderThemeQt::paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) +{ + return paintButton(o, i, r); } void RenderThemeQt::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const @@ -216,72 +383,140 @@ void RenderThemeQt::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* s // White-space is locked to pre style->setWhiteSpace(PRE); - setButtonSize(style); + FontDescription fontDescription = style->fontDescription(); + fontDescription.setIsAbsoluteSize(true); + +#ifdef Q_WS_MAC // Use fixed font size and family on Mac (like Safari does) + fontDescription.setSpecifiedSize(m_buttonFontPixelSize); + fontDescription.setComputedSize(m_buttonFontPixelSize); +#else + fontDescription.setSpecifiedSize(style->fontSize()); + fontDescription.setComputedSize(style->fontSize()); +#endif + FontFamily fontFamily; + fontFamily.setFamily(m_buttonFontFamily); + fontDescription.setFamily(fontFamily); + style->setFontDescription(fontDescription); + style->setLineHeight(RenderStyle::initialLineHeight()); + + setButtonSize(style); setButtonPadding(style); + + style->setColor(QApplication::palette().text().color()); } -bool RenderThemeQt::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) +void RenderThemeQt::setButtonSize(RenderStyle* style) const { - QStyle* style = 0; - QPainter* painter = 0; - QWidget* widget = 0; + computeSizeBasedOnStyle(style); +} - if (!getStylePainterAndWidgetFromPaintInfo(i, style, painter, widget)) - return true; +void RenderThemeQt::setButtonPadding(RenderStyle* style) const +{ + QStyleOptionButton styleOption; + styleOption.state |= QStyle::State_Small; + + // Fake a button rect here, since we're just computing deltas + QRect originalRect = QRect(0, 0, 100, 30); + styleOption.rect = originalRect; + + // Default padding is based on the button margin pixel metric + int buttonMargin = QApplication::style()->pixelMetric(QStyle::PM_ButtonMargin, + &styleOption, 0); + int paddingLeft = buttonMargin; + int paddingRight = buttonMargin; + int paddingTop = 1; + int paddingBottom = 0; + + // Then check if the style uses layout margins + QRect layoutRect = QApplication::style()->subElementRect(QStyle::SE_PushButtonLayoutItem, + &styleOption, 0); + if (!layoutRect.isNull()) { + QRect contentsRect = QApplication::style()->subElementRect(QStyle::SE_PushButtonContents, + &styleOption, 0); + paddingLeft = contentsRect.left() - layoutRect.left(); + paddingRight = layoutRect.right() - contentsRect.right(); + paddingTop = contentsRect.top() - layoutRect.top(); + + // Can't use this right now because we don't have the baseline to compensate + // paddingBottom = layoutRect.bottom() - contentsRect.bottom(); + } - QStyleOptionButton option; - if (widget) - option.initFrom(widget); - option.rect = r; + style->setPaddingLeft(Length(paddingLeft, Fixed)); + style->setPaddingRight(Length(paddingRight, Fixed)); + style->setPaddingTop(Length(paddingTop, Fixed)); + style->setPaddingBottom(Length(paddingBottom, Fixed)); +} - // Get the correct theme data for a button - EAppearance appearance = applyTheme(option, o); +bool RenderThemeQt::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) +{ + StylePainter p(i); + if (!p.isValid()) + return true; - if(appearance == PushButtonAppearance || appearance == ButtonAppearance) - style->drawControl(QStyle::CE_PushButton, &option, painter); - else if(appearance == RadioAppearance) - style->drawPrimitive(QStyle::PE_IndicatorRadioButton, &option, painter, widget); - else if(appearance == CheckboxAppearance) - style->drawPrimitive(QStyle::PE_IndicatorCheckBox, &option, painter, widget); + QStyleOptionButton option; + if (p.widget) + option.initFrom(p.widget); + + option.rect = r; + option.state |= QStyle::State_Small; + + ControlPart appearance = applyTheme(option, o); + if(appearance == PushButtonPart || appearance == ButtonPart) { + option.rect = inflateButtonRect(option.rect); + p.drawControl(QStyle::CE_PushButton, option); + } else if(appearance == RadioPart) { + p.drawControl(QStyle::CE_RadioButton, option); + } else if(appearance == CheckboxPart) { + p.drawControl(QStyle::CE_CheckBox, option); + } return false; } -void RenderThemeQt::setButtonSize(RenderStyle* style) const +void RenderThemeQt::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const { - setPrimitiveSize(style); + style->setBackgroundColor(Color::transparent); + style->setColor(QApplication::palette().text().color()); } bool RenderThemeQt::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) { - QStyle* style = 0; - QPainter* painter = 0; - QWidget* widget = 0; - - if (!getStylePainterAndWidgetFromPaintInfo(i, style, painter, widget)) + StylePainter p(i); + if (!p.isValid()) return true; QStyleOptionFrameV2 panel; - if (widget) - panel.initFrom(widget); + if (p.widget) + panel.initFrom(p.widget); + panel.rect = r; + panel.lineWidth = p.style->pixelMetric(QStyle::PM_DefaultFrameWidth, &panel, p.widget); panel.state |= QStyle::State_Sunken; panel.features = QStyleOptionFrameV2::None; - // Get the correct theme data for a button - EAppearance appearance = applyTheme(panel, o); - Q_ASSERT(appearance == TextFieldAppearance || appearance == SearchFieldAppearance); + // Get the correct theme data for a text field + ControlPart appearance = applyTheme(panel, o); + if (appearance != TextFieldPart + && appearance != SearchFieldPart + && appearance != TextAreaPart + && appearance != ListboxPart) + return true; // Now paint the text field. - style->drawPrimitive(QStyle::PE_PanelLineEdit, &panel, painter, widget); - style->drawPrimitive(QStyle::PE_FrameLineEdit, &panel, painter, widget); - + p.drawPrimitive(QStyle::PE_PanelLineEdit, panel); + return false; } -void RenderThemeQt::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const +void RenderThemeQt::adjustTextAreaStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const +{ + adjustTextFieldStyle(selector, style, element); +} + +bool RenderThemeQt::paintTextArea(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) { + return paintTextField(o, i, r); } void RenderThemeQt::adjustMenuListStyle(CSSStyleSelector*, RenderStyle* style, Element*) const @@ -294,55 +529,91 @@ void RenderThemeQt::adjustMenuListStyle(CSSStyleSelector*, RenderStyle* style, E // White-space is locked to pre style->setWhiteSpace(PRE); - setPrimitiveSize(style); + computeSizeBasedOnStyle(style); // Add in the padding that we'd like to use. setPopupPadding(style); - // Our font is locked to the appropriate system font size for the control. To clarify, we first use the CSS-specified font to figure out - // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate - // system font for the control size instead. - //setFontFromControlSize(selector, style); + style->setColor(QApplication::palette().text().color()); } -bool RenderThemeQt::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) +void RenderThemeQt::setPopupPadding(RenderStyle* style) const { - QStyle* style = 0; - QPainter* painter = 0; - QWidget* widget = 0; + const int padding = 8; + style->setPaddingLeft(Length(padding, Fixed)); - if (!getStylePainterAndWidgetFromPaintInfo(i, style, painter, widget)) + QStyleOptionComboBox opt; + int w = QApplication::style()->pixelMetric(QStyle::PM_ButtonIconSize, &opt, 0); + style->setPaddingRight(Length(padding + w, Fixed)); + + style->setPaddingTop(Length(2, Fixed)); + style->setPaddingBottom(Length(0, Fixed)); +} + + +bool RenderThemeQt::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) +{ + StylePainter p(i); + if (!p.isValid()) return true; QStyleOptionComboBox opt; - if (widget) - opt.initFrom(widget); - EAppearance appearance = applyTheme(opt, o); + if (p.widget) + opt.initFrom(p.widget); + ControlPart appearance = applyTheme(opt, o); + const QPoint topLeft = r.topLeft(); - painter->translate(topLeft); + p.painter->translate(topLeft); opt.rect.moveTo(QPoint(0,0)); opt.rect.setSize(r.size()); opt.frame = false; - style->drawComplexControl(QStyle::CC_ComboBox, &opt, painter, widget); - painter->translate(-topLeft); + p.drawComplexControl(QStyle::CC_ComboBox, opt); + p.painter->translate(-topLeft); return false; } - -bool RenderThemeQt::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& pi, - const IntRect& r) +void RenderThemeQt::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, + Element* e) const { - notImplemented(); - return RenderTheme::paintMenuListButton(o, pi, r); + // WORKAROUND because html4.css specifies -webkit-border-radius for <select> so we override it here + // see also http://bugs.webkit.org/show_bug.cgi?id=18399 + style->resetBorderRadius(); + + // Height is locked to auto. + style->setHeight(Length(Auto)); + + // White-space is locked to pre + style->setWhiteSpace(PRE); + + computeSizeBasedOnStyle(style); + + // Add in the padding that we'd like to use. + setPopupPadding(style); + + style->setColor(QApplication::palette().text().color()); } -void RenderThemeQt::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, - Element* e) const +bool RenderThemeQt::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& i, + const IntRect& r) { - notImplemented(); - RenderTheme::adjustMenuListButtonStyle(selector, style, e); + StylePainter p(i); + if (!p.isValid()) + return true; + + QStyleOptionComboBox option; + if (p.widget) + option.initFrom(p.widget); + applyTheme(option, o); + option.rect = r; + + // for drawing the combo box arrow, rely only on the fallback style + p.style = fallbackStyle(); + option.subControls = QStyle::SC_ComboBoxArrow; + p.drawComplexControl(QStyle::CC_ComboBox, option); + + return false; } bool RenderThemeQt::paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& pi, @@ -415,37 +686,24 @@ bool RenderThemeQt::paintSearchFieldResultsDecoration(RenderObject* o, const Ren return RenderTheme::paintSearchFieldResultsDecoration(o, pi, r); } -bool RenderThemeQt::supportsFocus(EAppearance appearance) const +bool RenderThemeQt::supportsFocus(ControlPart appearance) const { switch (appearance) { - case PushButtonAppearance: - case ButtonAppearance: - case TextFieldAppearance: - case MenulistAppearance: - case RadioAppearance: - case CheckboxAppearance: + case PushButtonPart: + case ButtonPart: + case TextFieldPart: + case TextAreaPart: + case ListboxPart: + case MenulistPart: + case RadioPart: + case CheckboxPart: return true; default: // No for all others... return false; } } -bool RenderThemeQt::getStylePainterAndWidgetFromPaintInfo(const RenderObject::PaintInfo& i, QStyle*& style, - QPainter*& painter, QWidget*& widget) const -{ - painter = (i.context ? static_cast<QPainter*>(i.context->platformContext()) : 0); - widget = 0; - QPaintDevice* dev = 0; - if (painter) - dev = painter->device(); - if (dev && dev->devType() == QInternal::Widget) - widget = static_cast<QWidget*>(dev); - style = (widget ? widget->style() : QApplication::style()); - - return (painter && style); -} - -EAppearance RenderThemeQt::applyTheme(QStyleOption& option, RenderObject* o) const +ControlPart RenderThemeQt::applyTheme(QStyleOption& option, RenderObject* o) const { // Default bits: no focus, no mouse over option.state &= ~(QStyle::State_HasFocus | QStyle::State_MouseOver); @@ -463,32 +721,26 @@ EAppearance RenderThemeQt::applyTheme(QStyleOption& option, RenderObject* o) con if (isHovered(o)) option.state |= QStyle::State_MouseOver; - EAppearance result = o->style()->appearance(); + ControlPart result = o->style()->appearance(); switch (result) { - case PushButtonAppearance: - case SquareButtonAppearance: - case ButtonAppearance: - case ButtonBevelAppearance: - case ListItemAppearance: - case MenulistButtonAppearance: - case ScrollbarButtonLeftAppearance: - case ScrollbarButtonRightAppearance: - case ScrollbarTrackHorizontalAppearance: - case ScrollbarTrackVerticalAppearance: - case ScrollbarThumbHorizontalAppearance: - case ScrollbarThumbVerticalAppearance: - case SearchFieldResultsButtonAppearance: - case SearchFieldCancelButtonAppearance: { + case PushButtonPart: + case SquareButtonPart: + case ButtonPart: + case ButtonBevelPart: + case ListItemPart: + case MenulistButtonPart: + case SearchFieldResultsButtonPart: + case SearchFieldCancelButtonPart: { if (isPressed(o)) option.state |= QStyle::State_Sunken; - else if (result == PushButtonAppearance) + else if (result == PushButtonPart) option.state |= QStyle::State_Raised; break; } } - if(result == RadioAppearance || result == CheckboxAppearance) + if(result == RadioPart || result == CheckboxPart) option.state |= (isChecked(o) ? QStyle::State_On : QStyle::State_Off); // If the webview has a custom palette, use it @@ -502,95 +754,192 @@ EAppearance RenderThemeQt::applyTheme(QStyleOption& option, RenderObject* o) con return result; } -void RenderThemeQt::setSizeFromFont(RenderStyle* style) const +void RenderTheme::adjustDefaultStyleSheet(CSSStyleSheet* style) { - // FIXME: Check is flawed, since it doesn't take min-width/max-width into account. - IntSize size = sizeForFont(style); - if (style->width().isIntrinsicOrAuto() && size.width() > 0) - style->setWidth(Length(size.width(), Fixed)); - if (style->height().isAuto() && size.height() > 0) - style->setHeight(Length(size.height(), Fixed)); + QFile platformStyleSheet(":/webcore/resources/html4-adjustments-qt.css"); + if (platformStyleSheet.open(QFile::ReadOnly)) { + QByteArray sheetData = platformStyleSheet.readAll(); + style->parseString(QString::fromUtf8(sheetData.constData(), sheetData.length())); + } } -IntSize RenderThemeQt::sizeForFont(RenderStyle* style) const +#if ENABLE(VIDEO) + +// Helper class to transform the painter's world matrix to the object's content area, scaled to 0,0,100,100 +class WorldMatrixTransformer { - const QFontMetrics fm(style->font().font()); - QSize size(0, 0); - switch (style->appearance()) { - case CheckboxAppearance: { - break; +public: + WorldMatrixTransformer(QPainter* painter, RenderObject* renderObject, const IntRect& r) : m_painter(painter) { + RenderStyle* style = renderObject->style(); + m_originalTransform = m_painter->transform(); + m_painter->translate(r.x() + style->paddingLeft().value(), r.y() + style->paddingTop().value()); + m_painter->scale((r.width() - style->paddingLeft().value() - style->paddingRight().value()) / 100.0, + (r.height() - style->paddingTop().value() - style->paddingBottom().value()) / 100.0); } - case RadioAppearance: { - break; - } - case PushButtonAppearance: - case ButtonAppearance: { - QSize sz = fm.size(Qt::TextShowMnemonic, QString::fromLatin1("X")); - QStyleOptionButton opt; - sz = QApplication::style()->sizeFromContents(QStyle::CT_PushButton, - &opt, sz, 0); - size.setHeight(sz.height()); - break; - } - case MenulistAppearance: { - QSize sz; - sz.setHeight(qMax(fm.lineSpacing(), 14) + 2); - QStyleOptionComboBox opt; - sz = QApplication::style()->sizeFromContents(QStyle::CT_ComboBox, - &opt, sz, 0); - size.setHeight(sz.height()); - break; - } - case TextFieldAppearance: { - const int verticalMargin = 1; - const int horizontalMargin = 2; - int h = qMax(fm.lineSpacing(), 14) + 2*verticalMargin; - int w = fm.width(QLatin1Char('x')) * 17 + 2*horizontalMargin; - QStyleOptionFrameV2 opt; - opt.lineWidth = QApplication::style()->pixelMetric(QStyle::PM_DefaultFrameWidth, - &opt, 0); - QSize sz = QApplication::style()->sizeFromContents(QStyle::CT_LineEdit, - &opt, - QSize(w, h).expandedTo(QApplication::globalStrut()), - 0); - size.setHeight(sz.height()); - break; + + ~WorldMatrixTransformer() { m_painter->setTransform(m_originalTransform); } + +private: + QPainter* m_painter; + QTransform m_originalTransform; +}; + +HTMLMediaElement* RenderThemeQt::getMediaElementFromRenderObject(RenderObject* o) const +{ + Node* node = o->element(); + Node* mediaNode = node ? node->shadowAncestorNode() : 0; + if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag))) + return 0; + + return static_cast<HTMLMediaElement*>(mediaNode); +} + +void RenderThemeQt::paintMediaBackground(QPainter* painter, const IntRect& r) const +{ + painter->setPen(Qt::NoPen); + static QColor transparentBlack(0,0,0,100); + painter->setBrush(transparentBlack); + painter->drawRoundedRect(r.x(), r.y(), r.width(), r.height(), 5.0, 5.0); +} + +QColor RenderThemeQt::getMediaControlForegroundColor(RenderObject* o) const +{ + QColor fgColor = platformActiveSelectionBackgroundColor(); + if (o && o->element()->active()) + fgColor = fgColor.lighter(); + return fgColor; +} + +bool RenderThemeQt::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +{ + return RenderTheme::paintMediaFullscreenButton(o, paintInfo, r); +} + +bool RenderThemeQt::paintMediaMuteButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +{ + HTMLMediaElement* mediaElement = getMediaElementFromRenderObject(o); + if (!mediaElement) + return false; + + StylePainter p(paintInfo); + if (!p.isValid()) + return true; + + p.painter->setRenderHint(QPainter::Antialiasing, true); + + paintMediaBackground(p.painter, r); + + WorldMatrixTransformer transformer(p.painter, o, r); + const QPointF speakerPolygon[6] = { QPointF(20, 30), QPointF(50, 30), QPointF(80, 0), + QPointF(80, 100), QPointF(50, 70), QPointF(20, 70)}; + + p.painter->setBrush(getMediaControlForegroundColor(o)); + p.painter->drawPolygon(speakerPolygon, 6); + + if (mediaElement->muted()) { + p.painter->setPen(Qt::red); + p.painter->drawLine(0, 100, 100, 0); } - default: - break; + + return false; +} + +bool RenderThemeQt::paintMediaPlayButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +{ + HTMLMediaElement* mediaElement = getMediaElementFromRenderObject(o); + if (!mediaElement) + return false; + + StylePainter p(paintInfo); + if (!p.isValid()) + return true; + + p.painter->setRenderHint(QPainter::Antialiasing, true); + + paintMediaBackground(p.painter, r); + + WorldMatrixTransformer transformer(p.painter, o, r); + p.painter->setBrush(getMediaControlForegroundColor(o)); + if (mediaElement->canPlay()) { + const QPointF playPolygon[3] = { QPointF(0, 0), QPointF(100, 50), QPointF(0, 100)}; + p.painter->drawPolygon(playPolygon, 3); + } else { + p.painter->drawRect(0, 0, 30, 100); + p.painter->drawRect(70, 0, 30, 100); } - return size; + + return false; } -void RenderThemeQt::setButtonPadding(RenderStyle* style) const +bool RenderThemeQt::paintMediaSeekBackButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { - const int padding = 8; - style->setPaddingLeft(Length(padding, Fixed)); - style->setPaddingRight(Length(padding, Fixed)); - style->setPaddingTop(Length(0, Fixed)); - style->setPaddingBottom(Length(0, Fixed)); + // We don't want to paint this at the moment. + return false; } -void RenderThemeQt::setPopupPadding(RenderStyle* style) const +bool RenderThemeQt::paintMediaSeekForwardButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { - const int padding = 8; - style->setPaddingLeft(Length(padding, Fixed)); - QStyleOptionComboBox opt; - int w = QApplication::style()->pixelMetric(QStyle::PM_ButtonIconSize, &opt, 0); - style->setPaddingRight(Length(padding + w, Fixed)); + // We don't want to paint this at the moment. + return false; +} - style->setPaddingTop(Length(1, Fixed)); - style->setPaddingBottom(Length(0, Fixed)); +bool RenderThemeQt::paintMediaSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +{ + HTMLMediaElement* mediaElement = getMediaElementFromRenderObject(o); + if (!mediaElement) + return false; + + StylePainter p(paintInfo); + if (!p.isValid()) + return true; + + p.painter->setRenderHint(QPainter::Antialiasing, true); + + paintMediaBackground(p.painter, r); + + if (MediaPlayer* player = mediaElement->player()) { + if (player->totalBytesKnown()) { + float percentLoaded = static_cast<float>(player->bytesLoaded()) / player->totalBytes(); + + WorldMatrixTransformer transformer(p.painter, o, r); + p.painter->setBrush(getMediaControlForegroundColor()); + p.painter->drawRect(0, 37, 100 * percentLoaded, 26); + } + } + + return false; } -void RenderThemeQt::setPrimitiveSize(RenderStyle* style) const +bool RenderThemeQt::paintMediaSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { - // If the width and height are both specified, then we have nothing to do. - if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) - return; + HTMLMediaElement* mediaElement = getMediaElementFromRenderObject(o->parent()); + if (!mediaElement) + return false; + + StylePainter p(paintInfo); + if (!p.isValid()) + return true; + + p.painter->setRenderHint(QPainter::Antialiasing, true); - // Use the font size to determine the intrinsic width of the control. - setSizeFromFont(style); + p.painter->setPen(Qt::NoPen); + p.painter->setBrush(getMediaControlForegroundColor(o)); + p.painter->drawRect(r.x(), r.y(), r.width(), r.height()); + + return false; +} +#endif + +void RenderThemeQt::adjustSliderThumbSize(RenderObject* o) const +{ + if (o->style()->appearance() == MediaSliderThumbPart) { + RenderStyle* parentStyle = o->parent()->style(); + Q_ASSERT(parentStyle); + + int parentHeight = parentStyle->height().value(); + o->style()->setWidth(Length(parentHeight / 3, Fixed)); + o->style()->setHeight(Length(parentHeight, Fixed)); + } } } |