summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/qt/RenderThemeQt.cpp
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
commit1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353 (patch)
tree4457a7306ea5acb43fe05bfe0973b1f7faf97ba2 /WebCore/platform/qt/RenderThemeQt.cpp
parent9364f22aed35e1a1e9d07c121510f80be3ab0502 (diff)
downloadexternal_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.cpp773
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));
+ }
}
}