2 * Copyright (C) 2007 Kevin Ollivier <kevino@theolliviers.com>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "RenderTheme.h"
30 #include "FrameView.h"
31 #include "GraphicsContext.h"
32 #include "HostWindow.h"
34 #include "NotImplemented.h"
35 #include "PaintInfo.h"
36 #include "RenderView.h"
41 #include <wx/dcgraph.h>
42 #include <wx/renderer.h>
43 #include <wx/dcclient.h>
44 #include <wx/scrolwin.h>
45 #include <wx/settings.h>
49 class RenderThemeWx : public RenderTheme {
51 RenderThemeWx() : RenderTheme() { }
52 virtual ~RenderThemeWx();
55 static PassRefPtr<RenderTheme> create();
57 // A method asking if the theme's controls actually care about redrawing when hovered.
58 virtual bool supportsHover(const RenderStyle*) const { return true; }
60 virtual bool paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& r)
62 return paintButton(o, i, r);
65 virtual void setCheckboxSize(RenderStyle*) const;
67 virtual bool paintRadio(RenderObject* o, const PaintInfo& i, const IntRect& r)
69 return paintButton(o, i, r);
72 virtual void setRadioSize(RenderStyle*) const;
74 virtual void adjustRepaintRect(const RenderObject*, IntRect&);
76 virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
77 virtual bool paintButton(RenderObject*, const PaintInfo&, const IntRect&);
79 virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
80 virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&);
82 virtual int minimumMenuListSize(RenderStyle*) const;
84 virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
85 virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&);
87 virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
88 virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
90 virtual bool isControlStyled(const RenderStyle*, const BorderData&,
91 const FillLayer&, const Color&) const;
93 virtual bool controlSupportsTints(const RenderObject*) const;
95 virtual void systemFont(int propId, FontDescription&) const;
97 virtual Color platformActiveSelectionBackgroundColor() const;
98 virtual Color platformInactiveSelectionBackgroundColor() const;
100 virtual Color platformActiveSelectionForegroundColor() const;
101 virtual Color platformInactiveSelectionForegroundColor() const;
103 virtual int popupInternalPaddingLeft(RenderStyle*) const;
104 virtual int popupInternalPaddingRight(RenderStyle*) const;
105 virtual int popupInternalPaddingTop(RenderStyle*) const;
106 virtual int popupInternalPaddingBottom(RenderStyle*) const;
109 void addIntrinsicMargins(RenderStyle*) const;
112 bool supportsFocus(ControlPart) const;
118 #define MINIMUM_MENU_LIST_SIZE 21
119 #define POPUP_INTERNAL_PADDING_LEFT 6
120 #define POPUP_INTERNAL_PADDING_TOP 2
121 #define POPUP_INTERNAL_PADDING_BOTTOM 2
124 #define POPUP_INTERNAL_PADDING_RIGHT 22
126 #define POPUP_INTERNAL_PADDING_RIGHT 20
129 RenderThemeWx::~RenderThemeWx()
133 PassRefPtr<RenderTheme> RenderThemeWx::create()
135 return adoptRef(new RenderThemeWx());
138 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
140 static RenderTheme* rt = RenderThemeWx::create().releaseRef();
144 wxWindow* nativeWindowForRenderObject(RenderObject* o)
146 FrameView* frameView = o->view()->frameView();
148 ASSERT(frameView->hostWindow());
149 return frameView->hostWindow()->platformPageClient();
153 bool RenderThemeWx::isControlStyled(const RenderStyle* style, const BorderData& border,
154 const FillLayer& background, const Color& backgroundColor) const
156 if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart)
157 return style->border() != border;
159 // Normally CSS can be used to set properties of form controls (such as adding a background bitmap).
160 // However, for this to work RenderThemeWx needs to adjust uncustomized elements (e.g. buttons) to reflect the
161 // changes made by CSS. Since we don't do that right now, the native parts of form elements appear in odd places.
162 // Until we have time to implement that support, we return false here, so that we ignore customizations
163 // and always use the native theme drawing to draw form controls.
167 void RenderThemeWx::adjustRepaintRect(const RenderObject* o, IntRect& r)
169 switch (o->style()->appearance()) {
171 r.setWidth(r.width() + 100);
179 bool RenderThemeWx::controlSupportsTints(const RenderObject* o) const
184 // Checkboxes only have tint when checked.
185 if (o->style()->appearance() == CheckboxPart)
188 // For now assume other controls have tint if enabled.
192 void RenderThemeWx::systemFont(int propId, FontDescription& fontDescription) const
197 void RenderThemeWx::addIntrinsicMargins(RenderStyle* style) const
199 // Cut out the intrinsic margins completely if we end up using a small font size
200 if (style->fontSize() < 11)
203 // Intrinsic margin value.
206 // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
207 if (style->width().isIntrinsicOrAuto()) {
208 if (style->marginLeft().quirk())
209 style->setMarginLeft(Length(m, Fixed));
211 if (style->marginRight().quirk())
212 style->setMarginRight(Length(m, Fixed));
215 if (style->height().isAuto()) {
216 if (style->marginTop().quirk())
217 style->setMarginTop(Length(m, Fixed));
219 if (style->marginBottom().quirk())
220 style->setMarginBottom(Length(m, Fixed));
224 void RenderThemeWx::setCheckboxSize(RenderStyle* style) const
226 // If the width and height are both specified, then we have nothing to do.
227 if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
230 // FIXME: A hard-coded size of 13 is used. This is wrong but necessary for now. It matches Firefox.
231 // At different DPI settings on Windows, querying the theme gives you a larger size that accounts for
232 // the higher DPI. Until our entire engine honors a DPI setting other than 96, we can't rely on the theme's
234 if (style->width().isIntrinsicOrAuto())
235 style->setWidth(Length(13, Fixed));
237 if (style->height().isAuto())
238 style->setHeight(Length(13, Fixed));
241 void RenderThemeWx::setRadioSize(RenderStyle* style) const
243 // This is the same as checkboxes.
244 setCheckboxSize(style);
247 bool RenderThemeWx::supportsFocus(ControlPart part) const
255 default: // No for all others...
260 void RenderThemeWx::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
262 addIntrinsicMargins(style);
265 bool RenderThemeWx::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& r)
267 wxWindow* window = nativeWindowForRenderObject(o);
268 wxDC* dc = static_cast<wxDC*>(i.context->platformContext());
269 LocalDC localDC(dc, r);
276 flags |= wxCONTROL_DISABLED;
278 ControlPart part = o->style()->appearance();
279 if (supportsFocus(part) && isFocused(o))
280 flags |= wxCONTROL_FOCUSED;
283 flags |= wxCONTROL_PRESSED;
285 if (part == PushButtonPart || part == ButtonPart)
286 wxRendererNative::Get().DrawPushButton(window, *localDC.context(), rect, flags);
287 else if(part == RadioPart) {
289 flags |= wxCONTROL_CHECKED;
290 #if wxCHECK_VERSION(2,9,1)
291 wxRendererNative::Get().DrawRadioBitmap(window, *localDC.context(), rect, flags);
292 #elif wxCHECK_VERSION(2,9,0)
293 wxRendererNative::Get().DrawRadioButton(window, *localDC.context(), rect, flags);
295 wxRenderer_DrawRadioButton(window, *localDC.context(), rect, flags);
298 else if(part == CheckboxPart) {
300 flags |= wxCONTROL_CHECKED;
301 wxRendererNative::Get().DrawCheckBox(window, *localDC.context(), rect, flags);
306 void RenderThemeWx::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
311 bool RenderThemeWx::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& r)
313 wxWindow* window = nativeWindowForRenderObject(o);
314 wxDC* dc = static_cast<wxDC*>(i.context->platformContext());
315 LocalDC localDC(dc, r);
320 ControlPart part = o->style()->appearance();
321 if (supportsFocus(part) && isFocused(o))
322 flags |= wxCONTROL_FOCUSED;
324 #if wxCHECK_VERSION(2,9,0)
325 wxRendererNative::Get().DrawTextCtrl(window, *localDC.context(), rect, flags);
327 wxRenderer_DrawTextCtrl(window, *localDC.context(), r, 0);
333 int RenderThemeWx::minimumMenuListSize(RenderStyle*) const
335 return MINIMUM_MENU_LIST_SIZE;
338 void RenderThemeWx::adjustMenuListStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
340 style->resetBorder();
342 // Height is locked to auto.
343 style->setHeight(Length(Auto));
345 style->setPaddingTop(Length(2, Fixed));
346 style->setPaddingBottom(Length(2, Fixed));
349 bool RenderThemeWx::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& r)
351 wxWindow* window = nativeWindowForRenderObject(o);
352 wxDC* dc = static_cast<wxDC*>(i.context->platformContext());
354 LocalDC localDC(dc, r);
359 flags |= wxCONTROL_DISABLED;
361 if (supportsFocus(o->style()->appearance()) && isFocused(o))
362 flags |= wxCONTROL_FOCUSED;
365 flags |= wxCONTROL_PRESSED;
367 #if wxCHECK_VERSION(2,9,0)
368 wxRendererNative::Get().DrawChoice(window, *localDC.context(), rect, flags);
370 wxRenderer_DrawChoice(window, *localDC.context(), rect, flags);
376 void RenderThemeWx::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
381 bool RenderThemeWx::paintMenuListButton(RenderObject* o, const PaintInfo& i, const IntRect& r)
383 wxWindow* window = nativeWindowForRenderObject(o);
384 wxDC* dc = static_cast<wxDC*>(i.context->platformContext());
385 LocalDC localDC(dc, r);
390 flags |= wxCONTROL_DISABLED;
392 if (supportsFocus(o->style()->appearance()) && isFocused(o))
393 flags |= wxCONTROL_FOCUSED;
396 flags |= wxCONTROL_PRESSED;
398 wxRendererNative::Get().DrawComboBoxDropButton(window, *localDC.context(), rect, flags);
404 Color RenderThemeWx::platformActiveSelectionBackgroundColor() const
406 return wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
409 Color RenderThemeWx::platformInactiveSelectionBackgroundColor() const
411 return wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW);
414 Color RenderThemeWx::platformActiveSelectionForegroundColor() const
416 // FIXME: Get wx to return the correct value for each platform.
420 return Color(255, 255, 255);
424 Color RenderThemeWx::platformInactiveSelectionForegroundColor() const
429 return Color(255, 255, 255);
433 int RenderThemeWx::popupInternalPaddingLeft(RenderStyle*) const
435 return POPUP_INTERNAL_PADDING_LEFT;
438 int RenderThemeWx::popupInternalPaddingRight(RenderStyle*) const
440 return POPUP_INTERNAL_PADDING_RIGHT;
443 int RenderThemeWx::popupInternalPaddingTop(RenderStyle*) const
445 return POPUP_INTERNAL_PADDING_TOP;
448 int RenderThemeWx::popupInternalPaddingBottom(RenderStyle*) const
450 return POPUP_INTERNAL_PADDING_BOTTOM;