2 * This file is part of the WebKit project.
4 * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
5 * 2006 Nikolas Zimmermann <zimmermann@kde.org>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
31 #include <QStyleOptionButton>
34 #include "RenderTheme.h"
35 #include "GraphicsContext.h"
36 #include "RenderPopupMenuQt.h"
38 #define notImplemented() do { fprintf(stderr, "FIXME: UNIMPLEMENTED: %s:%d\n", __FILE__, __LINE__); } while(0)
42 class RenderThemeQt : public RenderTheme
45 RenderThemeQt() : RenderTheme() { }
47 // A method asking if the theme's controls actually care about redrawing when hovered.
48 virtual bool supportsHover(const RenderStyle*) const { return true; }
50 virtual bool paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
52 return paintButton(o, i, r);
55 virtual void setCheckboxSize(RenderStyle*) const;
57 virtual bool paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
59 return paintButton(o, i, r);
62 virtual void setRadioSize(RenderStyle*) const;
64 virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
65 virtual bool paintButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
67 virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
68 virtual bool paintTextField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
70 virtual bool isControlStyled(const RenderStyle*, const BorderData&,
71 const BackgroundLayer&, const Color&) const;
73 virtual bool controlSupportsTints(const RenderObject*) const;
75 virtual void systemFont(int propId, FontDescription&) const;
76 virtual RenderPopupMenu* createPopupMenu(RenderArena*, Document*, RenderMenuList*);
79 void addIntrinsicMargins(RenderStyle*) const;
82 bool supportsFocus(EAppearance) const;
84 bool getStylePainterAndWidgetFromPaintInfo(const RenderObject::PaintInfo&, QStyle*&, QPainter*&, QWidget*&) const;
85 EAppearance applyTheme(QStyleOption&, RenderObject*) const;
90 static RenderThemeQt rt;
94 bool RenderThemeQt::isControlStyled(const RenderStyle* style, const BorderData& border,
95 const BackgroundLayer& background, const Color& backgroundColor) const
97 if (style->appearance() == TextFieldAppearance || style->appearance() == TextAreaAppearance)
98 return style->border() != border;
100 return RenderTheme::isControlStyled(style, border, background, backgroundColor);
103 bool RenderThemeQt::controlSupportsTints(const RenderObject* o) const
108 // Checkboxes only have tint when checked.
109 if (o->style()->appearance() == CheckboxAppearance)
112 // For now assume other controls have tint if enabled.
116 void RenderThemeQt::systemFont(int propId, FontDescription& fontDescription) const
121 RenderPopupMenu* RenderThemeQt::createPopupMenu(RenderArena* arena, Document* doc, RenderMenuList* menuList)
123 return new (arena) RenderPopupMenuQt(doc, menuList);
126 void RenderThemeQt::addIntrinsicMargins(RenderStyle* style) const
128 // Cut out the intrinsic margins completely if we end up using a small font size
129 if (style->fontSize() < 11)
132 // Intrinsic margin value.
135 // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
136 if (style->width().isIntrinsicOrAuto()) {
137 if (style->marginLeft().quirk())
138 style->setMarginLeft(Length(m, Fixed));
140 if (style->marginRight().quirk())
141 style->setMarginRight(Length(m, Fixed));
144 if (style->height().isAuto()) {
145 if (style->marginTop().quirk())
146 style->setMarginTop(Length(m, Fixed));
148 if (style->marginBottom().quirk())
149 style->setMarginBottom(Length(m, Fixed));
153 bool RenderThemeQt::getStylePainterAndWidgetFromPaintInfo(const RenderObject::PaintInfo& i, QStyle*& style, QPainter*& painter, QWidget*& widget) const
155 painter = (i.p ? static_cast<QPainter*>(i.p->platformContext()) : 0);
156 widget = (painter ? static_cast<QWidget*>(painter->device()) : 0);
157 style = (widget ? widget->style() : 0);
159 return (painter && widget && style);
162 void RenderThemeQt::setCheckboxSize(RenderStyle* style) const
164 // If the width and height are both specified, then we have nothing to do.
165 if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
168 // FIXME: A hard-coded size of 13 is used. This is wrong but necessary for now. It matches Firefox.
169 // At different DPI settings on Windows, querying the theme gives you a larger size that accounts for
170 // the higher DPI. Until our entire engine honors a DPI setting other than 96, we can't rely on the theme's
172 if (style->width().isIntrinsicOrAuto())
173 style->setWidth(Length(13, Fixed));
175 if (style->height().isAuto())
176 style->setHeight(Length(13, Fixed));
179 void RenderThemeQt::setRadioSize(RenderStyle* style) const
181 // This is the same as checkboxes.
182 setCheckboxSize(style);
185 bool RenderThemeQt::supportsFocus(EAppearance appearance) const
187 switch (appearance) {
188 case PushButtonAppearance:
189 case ButtonAppearance:
190 case TextFieldAppearance:
192 default: // No for all others...
197 EAppearance RenderThemeQt::applyTheme(QStyleOption& option, RenderObject* o) const
199 // Default bits: no focus, no mouse over
200 option.state &= ~(QStyle::State_HasFocus | QStyle::State_MouseOver);
203 option.state &= ~QStyle::State_Enabled;
205 if (isReadOnlyControl(o))
206 // Readonly is supported on textfields.
207 option.state |= QStyle::State_ReadOnly;
209 if (supportsFocus(o->style()->appearance()) && isFocused(o))
210 option.state |= QStyle::State_HasFocus;
213 option.state |= QStyle::State_MouseOver;
216 option.state |= QStyle::State_Sunken;
218 EAppearance result = o->style()->appearance();
219 if(result == RadioAppearance || result == CheckboxAppearance)
220 option.state |= (isChecked(o) ? QStyle::State_On : QStyle::State_Off);
225 void RenderThemeQt::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
227 addIntrinsicMargins(style);
230 bool RenderThemeQt::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
233 QPainter* painter = 0;
236 if (!getStylePainterAndWidgetFromPaintInfo(i, style, painter, widget))
239 QStyleOptionButton option;
240 option.initFrom(widget);
243 // Get the correct theme data for a button
244 EAppearance appearance = applyTheme(option, o);
246 if(appearance == PushButtonAppearance || appearance == ButtonAppearance)
247 style->drawControl(QStyle::CE_PushButton, &option, painter);
248 else if(appearance == RadioAppearance)
249 style->drawControl(QStyle::CE_RadioButton, &option, painter);
250 else if(appearance == CheckboxAppearance)
251 style->drawControl(QStyle::CE_CheckBox, &option, painter);
256 void RenderThemeQt::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
258 addIntrinsicMargins(style);
261 bool RenderThemeQt::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
264 QPainter* painter = 0;
267 if (!getStylePainterAndWidgetFromPaintInfo(i, style, painter, widget))
272 // Get the correct theme data for a button
273 EAppearance appearance = applyTheme(option, o);
274 Q_ASSERT(appearance == TextFieldAppearance);
276 // Now paint the text field.
277 // FIXME: this is not enough for sure! (use 'option'...)
278 painter->drawRect(r);