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"
33 #include "NotImplemented.h"
34 #include "PaintInfo.h"
35 #include "RenderView.h"
40 #include <wx/dcgraph.h>
41 #include <wx/renderer.h>
42 #include <wx/dcclient.h>
43 #include <wx/scrolwin.h>
44 #include <wx/settings.h>
48 IntRect getAdjustedRect(wxDC* dc, const IntRect& r)
51 // On Mac, wxGraphicsContext and wxDC share the same native implementation,
52 // and so transformations are available.
53 // On Win and Linux, however, this is not true and transforms are lost,
54 // so we need to restore them here.
55 #if !wxCHECK_VERSION(2, 9, 2) && USE(WXGC) && !defined(__WXMAC__)
56 LOG_ERROR("Rect is (%d, %d)\n", rect.x(), rect.y());
60 wxGCDC* gcdc = static_cast<wxGCDC*>(dc);
61 wxGraphicsContext* gc = gcdc->GetGraphicsContext();
62 gc->GetTransform().TransformPoint(&xtrans, &ytrans);
63 rect.setX(r.x() + (int)xtrans);
64 rect.setY(r.y() + (int)ytrans);
65 LOG_ERROR("Transform is (%f, %f), (%d, %d)\n", xtrans, ytrans, rect.x(), rect.y());
71 class RenderThemeWx : public RenderTheme {
73 RenderThemeWx() : RenderTheme() { }
74 virtual ~RenderThemeWx();
77 static PassRefPtr<RenderTheme> create();
79 // A method asking if the theme's controls actually care about redrawing when hovered.
80 virtual bool supportsHover(const RenderStyle*) const { return true; }
82 virtual bool paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& r)
84 return paintButton(o, i, r);
87 virtual void setCheckboxSize(RenderStyle*) const;
89 virtual bool paintRadio(RenderObject* o, const PaintInfo& i, const IntRect& r)
91 return paintButton(o, i, r);
94 virtual void setRadioSize(RenderStyle*) const;
96 virtual void adjustRepaintRect(const RenderObject*, IntRect&);
98 virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
99 virtual bool paintButton(RenderObject*, const PaintInfo&, const IntRect&);
101 virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
102 virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&);
104 virtual int minimumMenuListSize(RenderStyle*) const;
106 virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
107 virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&);
109 virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
110 virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
112 virtual bool isControlStyled(const RenderStyle*, const BorderData&,
113 const FillLayer&, const Color&) const;
115 virtual bool controlSupportsTints(const RenderObject*) const;
117 virtual void systemFont(int propId, FontDescription&) const;
119 virtual Color platformActiveSelectionBackgroundColor() const;
120 virtual Color platformInactiveSelectionBackgroundColor() const;
122 virtual Color platformActiveSelectionForegroundColor() const;
123 virtual Color platformInactiveSelectionForegroundColor() const;
125 virtual int popupInternalPaddingLeft(RenderStyle*) const;
126 virtual int popupInternalPaddingRight(RenderStyle*) const;
127 virtual int popupInternalPaddingTop(RenderStyle*) const;
128 virtual int popupInternalPaddingBottom(RenderStyle*) const;
131 void addIntrinsicMargins(RenderStyle*) const;
134 bool supportsFocus(ControlPart) const;
140 #define MINIMUM_MENU_LIST_SIZE 21
141 #define POPUP_INTERNAL_PADDING_LEFT 6
142 #define POPUP_INTERNAL_PADDING_TOP 2
143 #define POPUP_INTERNAL_PADDING_BOTTOM 2
146 #define POPUP_INTERNAL_PADDING_RIGHT 22
148 #define POPUP_INTERNAL_PADDING_RIGHT 20
151 RenderThemeWx::~RenderThemeWx()
155 PassRefPtr<RenderTheme> RenderThemeWx::create()
157 return adoptRef(new RenderThemeWx());
160 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
162 static RenderTheme* rt = RenderThemeWx::create().releaseRef();
166 wxWindow* nativeWindowForRenderObject(RenderObject* o)
168 FrameView* frameView = o->view()->frameView();
170 ASSERT(frameView->hostWindow());
171 return frameView->hostWindow()->platformPageClient();
175 bool RenderThemeWx::isControlStyled(const RenderStyle* style, const BorderData& border,
176 const FillLayer& background, const Color& backgroundColor) const
178 if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart)
179 return style->border() != border;
181 // Normally CSS can be used to set properties of form controls (such as adding a background bitmap).
182 // However, for this to work RenderThemeWx needs to adjust uncustomized elements (e.g. buttons) to reflect the
183 // changes made by CSS. Since we don't do that right now, the native parts of form elements appear in odd places.
184 // Until we have time to implement that support, we return false here, so that we ignore customizations
185 // and always use the native theme drawing to draw form controls.
189 void RenderThemeWx::adjustRepaintRect(const RenderObject* o, IntRect& r)
191 switch (o->style()->appearance()) {
193 r.setWidth(r.width() + 100);
201 bool RenderThemeWx::controlSupportsTints(const RenderObject* o) const
206 // Checkboxes only have tint when checked.
207 if (o->style()->appearance() == CheckboxPart)
210 // For now assume other controls have tint if enabled.
214 void RenderThemeWx::systemFont(int propId, FontDescription& fontDescription) const
219 void RenderThemeWx::addIntrinsicMargins(RenderStyle* style) const
221 // Cut out the intrinsic margins completely if we end up using a small font size
222 if (style->fontSize() < 11)
225 // Intrinsic margin value.
228 // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
229 if (style->width().isIntrinsicOrAuto()) {
230 if (style->marginLeft().quirk())
231 style->setMarginLeft(Length(m, Fixed));
233 if (style->marginRight().quirk())
234 style->setMarginRight(Length(m, Fixed));
237 if (style->height().isAuto()) {
238 if (style->marginTop().quirk())
239 style->setMarginTop(Length(m, Fixed));
241 if (style->marginBottom().quirk())
242 style->setMarginBottom(Length(m, Fixed));
246 void RenderThemeWx::setCheckboxSize(RenderStyle* style) const
248 // If the width and height are both specified, then we have nothing to do.
249 if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
252 // FIXME: A hard-coded size of 13 is used. This is wrong but necessary for now. It matches Firefox.
253 // At different DPI settings on Windows, querying the theme gives you a larger size that accounts for
254 // the higher DPI. Until our entire engine honors a DPI setting other than 96, we can't rely on the theme's
256 if (style->width().isIntrinsicOrAuto())
257 style->setWidth(Length(13, Fixed));
259 if (style->height().isAuto())
260 style->setHeight(Length(13, Fixed));
263 void RenderThemeWx::setRadioSize(RenderStyle* style) const
265 // This is the same as checkboxes.
266 setCheckboxSize(style);
269 bool RenderThemeWx::supportsFocus(ControlPart part) const
277 default: // No for all others...
282 void RenderThemeWx::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
284 addIntrinsicMargins(style);
287 bool RenderThemeWx::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& r)
289 wxWindow* window = nativeWindowForRenderObject(o);
290 wxDC* dc = static_cast<wxDC*>(i.context->platformContext());
293 IntRect rect = getAdjustedRect(dc, r);
296 flags |= wxCONTROL_DISABLED;
298 ControlPart part = o->style()->appearance();
299 if (supportsFocus(part) && isFocused(o))
300 flags |= wxCONTROL_FOCUSED;
303 flags |= wxCONTROL_PRESSED;
305 if (part == PushButtonPart || part == ButtonPart)
306 wxRendererNative::Get().DrawPushButton(window, *dc, rect, flags);
307 else if(part == RadioPart) {
309 flags |= wxCONTROL_CHECKED;
310 #if wxCHECK_VERSION(2,9,1)
311 wxRendererNative::Get().DrawRadioBitmap(window, *dc, rect, flags);
312 #elif wxCHECK_VERSION(2,9,0)
313 wxRendererNative::Get().DrawRadioButton(window, *dc, rect, flags);
315 wxRenderer_DrawRadioButton(window, *dc, rect, flags);
318 else if(part == CheckboxPart) {
320 flags |= wxCONTROL_CHECKED;
321 wxRendererNative::Get().DrawCheckBox(window, *dc, rect, flags);
326 void RenderThemeWx::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
331 bool RenderThemeWx::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& r)
333 wxWindow* window = nativeWindowForRenderObject(o);
334 wxDC* dc = static_cast<wxDC*>(i.context->platformContext());
337 IntRect rect = getAdjustedRect(dc, r);
339 ControlPart part = o->style()->appearance();
340 if (supportsFocus(part) && isFocused(o))
341 flags |= wxCONTROL_FOCUSED;
343 #if wxCHECK_VERSION(2,9,0)
344 wxRendererNative::Get().DrawTextCtrl(window, *dc, rect, flags);
346 wxRenderer_DrawTextCtrl(window, *dc, r, 0);
352 int RenderThemeWx::minimumMenuListSize(RenderStyle*) const
354 return MINIMUM_MENU_LIST_SIZE;
357 void RenderThemeWx::adjustMenuListStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
359 style->resetBorder();
361 // Height is locked to auto.
362 style->setHeight(Length(Auto));
364 style->setPaddingTop(Length(2, Fixed));
365 style->setPaddingBottom(Length(2, Fixed));
368 bool RenderThemeWx::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& r)
370 wxWindow* window = nativeWindowForRenderObject(o);
371 wxDC* dc = static_cast<wxDC*>(i.context->platformContext());
373 IntRect rect = getAdjustedRect(dc, r);
377 flags |= wxCONTROL_DISABLED;
379 if (supportsFocus(o->style()->appearance()) && isFocused(o))
380 flags |= wxCONTROL_FOCUSED;
383 flags |= wxCONTROL_PRESSED;
385 #if wxCHECK_VERSION(2,9,0)
386 wxRendererNative::Get().DrawChoice(window, *dc, rect, flags);
388 wxRenderer_DrawChoice(window, *dc, rect, flags);
394 void RenderThemeWx::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
399 bool RenderThemeWx::paintMenuListButton(RenderObject* o, const PaintInfo& i, const IntRect& r)
401 wxWindow* window = nativeWindowForRenderObject(o);
402 wxDC* dc = static_cast<wxDC*>(i.context->platformContext());
404 IntRect rect = getAdjustedRect(dc, r);
408 flags |= wxCONTROL_DISABLED;
410 if (supportsFocus(o->style()->appearance()) && isFocused(o))
411 flags |= wxCONTROL_FOCUSED;
414 flags |= wxCONTROL_PRESSED;
416 wxRendererNative::Get().DrawComboBoxDropButton(window, *dc, rect, flags);
422 Color RenderThemeWx::platformActiveSelectionBackgroundColor() const
424 return wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
427 Color RenderThemeWx::platformInactiveSelectionBackgroundColor() const
429 return wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW);
432 Color RenderThemeWx::platformActiveSelectionForegroundColor() const
434 // FIXME: Get wx to return the correct value for each platform.
438 return Color(255, 255, 255);
442 Color RenderThemeWx::platformInactiveSelectionForegroundColor() const
447 return Color(255, 255, 255);
451 int RenderThemeWx::popupInternalPaddingLeft(RenderStyle*) const
453 return POPUP_INTERNAL_PADDING_LEFT;
456 int RenderThemeWx::popupInternalPaddingRight(RenderStyle*) const
458 return POPUP_INTERNAL_PADDING_RIGHT;
461 int RenderThemeWx::popupInternalPaddingTop(RenderStyle*) const
463 return POPUP_INTERNAL_PADDING_TOP;
466 int RenderThemeWx::popupInternalPaddingBottom(RenderStyle*) const
468 return POPUP_INTERNAL_PADDING_BOTTOM;