• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 Kevin Ollivier <kevino@theolliviers.com>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25 
26 #include "config.h"
27 #include "RenderTheme.h"
28 
29 #include "Document.h"
30 #include "FrameView.h"
31 #include "GraphicsContext.h"
32 #include "HostWindow.h"
33 #include "NotImplemented.h"
34 #include "RenderView.h"
35 
36 #include <wx/defs.h>
37 
38 #include <wx/dc.h>
39 #include <wx/dcgraph.h>
40 #include <wx/renderer.h>
41 #include <wx/dcclient.h>
42 #include <wx/scrolwin.h>
43 #include <wx/settings.h>
44 
45 namespace WebCore {
46 
47 class RenderThemeWx : public RenderTheme {
48 private:
RenderThemeWx()49     RenderThemeWx() : RenderTheme() { }
50     virtual ~RenderThemeWx();
51 
52 public:
53     static PassRefPtr<RenderTheme> create();
54 
55     // A method asking if the theme's controls actually care about redrawing when hovered.
supportsHover(const RenderStyle *) const56     virtual bool supportsHover(const RenderStyle*) const { return true; }
57 
paintCheckbox(RenderObject * o,const RenderObject::PaintInfo & i,const IntRect & r)58     virtual bool paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
59     {
60         return paintButton(o, i, r);
61     }
62 
63     virtual void setCheckboxSize(RenderStyle*) const;
64 
paintRadio(RenderObject * o,const RenderObject::PaintInfo & i,const IntRect & r)65     virtual bool paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
66     {
67         return paintButton(o, i, r);
68     }
69 
70     virtual void setRadioSize(RenderStyle*) const;
71 
72     virtual void adjustRepaintRect(const RenderObject*, IntRect&);
73 
74     virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
75     virtual bool paintButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
76 
77     virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
78     virtual bool paintTextField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
79 
80     virtual int minimumMenuListSize(RenderStyle*) const;
81 
82     virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
83     virtual bool paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
84 
85     virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
86     virtual bool paintMenuListButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
87 
88     virtual bool isControlStyled(const RenderStyle*, const BorderData&,
89                                  const FillLayer&, const Color&) const;
90 
91     virtual bool controlSupportsTints(const RenderObject*) const;
92 
93     virtual void systemFont(int propId, FontDescription&) const;
94 
95     virtual Color platformActiveSelectionBackgroundColor() const;
96     virtual Color platformInactiveSelectionBackgroundColor() const;
97 
98     virtual Color platformActiveSelectionForegroundColor() const;
99     virtual Color platformInactiveSelectionForegroundColor() const;
100 
101     virtual int popupInternalPaddingLeft(RenderStyle*) const;
102     virtual int popupInternalPaddingRight(RenderStyle*) const;
103     virtual int popupInternalPaddingTop(RenderStyle*) const;
104     virtual int popupInternalPaddingBottom(RenderStyle*) const;
105 
106 private:
107     void addIntrinsicMargins(RenderStyle*) const;
108     void close();
109 
110     bool supportsFocus(ControlPart) const;
111 };
112 
113 
114 // Constants
115 
116 #define MINIMUM_MENU_LIST_SIZE 21
117 #define POPUP_INTERNAL_PADDING_LEFT 6
118 #define POPUP_INTERNAL_PADDING_TOP 2
119 #define POPUP_INTERNAL_PADDING_BOTTOM 2
120 
121 #ifdef __WXMAC__
122 #define POPUP_INTERNAL_PADDING_RIGHT 22
123 #else
124 #define POPUP_INTERNAL_PADDING_RIGHT 20
125 #endif
126 
~RenderThemeWx()127 RenderThemeWx::~RenderThemeWx()
128 {
129 }
130 
create()131 PassRefPtr<RenderTheme> RenderThemeWx::create()
132 {
133     return adoptRef(new RenderThemeWx());
134 }
135 
themeForPage(Page * page)136 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
137 {
138     static RenderTheme* rt = RenderThemeWx::create().releaseRef();
139     return rt;
140 }
141 
nativeWindowForRenderObject(RenderObject * o)142 wxWindow* nativeWindowForRenderObject(RenderObject* o)
143 {
144     FrameView* frameView = o->view()->frameView();
145     ASSERT(frameView);
146     ASSERT(frameView->hostWindow());
147     return frameView->hostWindow()->platformPageClient();
148 }
149 
150 
isControlStyled(const RenderStyle * style,const BorderData & border,const FillLayer & background,const Color & backgroundColor) const151 bool RenderThemeWx::isControlStyled(const RenderStyle* style, const BorderData& border,
152                                      const FillLayer& background, const Color& backgroundColor) const
153 {
154     if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart)
155         return style->border() != border;
156 
157     // Normally CSS can be used to set properties of form controls (such as adding a background bitmap).
158     // However, for this to work RenderThemeWx needs to adjust uncustomized elements (e.g. buttons) to reflect the
159     // changes made by CSS. Since we don't do that right now, the native parts of form elements appear in odd places.
160     // Until we have time to implement that support, we return false here, so that we ignore customizations
161     // and always use the native theme drawing to draw form controls.
162     return false;
163 }
164 
adjustRepaintRect(const RenderObject * o,IntRect & r)165 void RenderThemeWx::adjustRepaintRect(const RenderObject* o, IntRect& r)
166 {
167     switch (o->style()->appearance()) {
168         case MenulistPart: {
169             r.setWidth(r.width() + 100);
170             break;
171         }
172         default:
173             break;
174     }
175 }
176 
controlSupportsTints(const RenderObject * o) const177 bool RenderThemeWx::controlSupportsTints(const RenderObject* o) const
178 {
179     if (!isEnabled(o))
180         return false;
181 
182     // Checkboxes only have tint when checked.
183     if (o->style()->appearance() == CheckboxPart)
184         return isChecked(o);
185 
186     // For now assume other controls have tint if enabled.
187     return true;
188 }
189 
systemFont(int propId,FontDescription & fontDescription) const190 void RenderThemeWx::systemFont(int propId, FontDescription& fontDescription) const
191 {
192     // no-op
193 }
194 
addIntrinsicMargins(RenderStyle * style) const195 void RenderThemeWx::addIntrinsicMargins(RenderStyle* style) const
196 {
197     // Cut out the intrinsic margins completely if we end up using a small font size
198     if (style->fontSize() < 11)
199         return;
200 
201     // Intrinsic margin value.
202     const int m = 2;
203 
204     // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
205     if (style->width().isIntrinsicOrAuto()) {
206         if (style->marginLeft().quirk())
207             style->setMarginLeft(Length(m, Fixed));
208 
209         if (style->marginRight().quirk())
210             style->setMarginRight(Length(m, Fixed));
211     }
212 
213     if (style->height().isAuto()) {
214         if (style->marginTop().quirk())
215             style->setMarginTop(Length(m, Fixed));
216 
217         if (style->marginBottom().quirk())
218             style->setMarginBottom(Length(m, Fixed));
219     }
220 }
221 
setCheckboxSize(RenderStyle * style) const222 void RenderThemeWx::setCheckboxSize(RenderStyle* style) const
223 {
224     // If the width and height are both specified, then we have nothing to do.
225     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
226         return;
227 
228     // FIXME:  A hard-coded size of 13 is used.  This is wrong but necessary for now.  It matches Firefox.
229     // At different DPI settings on Windows, querying the theme gives you a larger size that accounts for
230     // the higher DPI.  Until our entire engine honors a DPI setting other than 96, we can't rely on the theme's
231     // metrics.
232     if (style->width().isIntrinsicOrAuto())
233         style->setWidth(Length(13, Fixed));
234 
235     if (style->height().isAuto())
236         style->setHeight(Length(13, Fixed));
237 }
238 
setRadioSize(RenderStyle * style) const239 void RenderThemeWx::setRadioSize(RenderStyle* style) const
240 {
241     // This is the same as checkboxes.
242     setCheckboxSize(style);
243 }
244 
supportsFocus(ControlPart part) const245 bool RenderThemeWx::supportsFocus(ControlPart part) const
246 {
247     switch (part) {
248         case PushButtonPart:
249         case ButtonPart:
250         case TextFieldPart:
251             return true;
252         default: // No for all others...
253             return false;
254     }
255 }
256 
adjustButtonStyle(CSSStyleSelector * selector,RenderStyle * style,Element * e) const257 void RenderThemeWx::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
258 {
259     addIntrinsicMargins(style);
260 }
261 
paintButton(RenderObject * o,const RenderObject::PaintInfo & i,const IntRect & r)262 bool RenderThemeWx::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
263 {
264     wxWindow* window = nativeWindowForRenderObject(o);
265     wxDC* dc = static_cast<wxDC*>(i.context->platformContext());
266     int flags = 0;
267 
268     IntRect rect = r;
269 
270 // On Mac, wxGraphicsContext and wxDC share the same native implementation,
271 // and so transformations are available.
272 // On Win and Linux, however, this is not true and transforms are lost,
273 // so we need to restore them here.
274 #if USE(WXGC) && !defined(__WXMAC__)
275     double xtrans = 0;
276     double ytrans = 0;
277 
278     wxGCDC* gcdc = static_cast<wxGCDC*>(dc);
279     wxGraphicsContext* gc = gcdc->GetGraphicsContext();
280     gc->GetTransform().TransformPoint(&xtrans, &ytrans);
281     rect.setX(r.x() + (int)xtrans);
282     rect.setY(r.y() + (int)ytrans);
283 #endif
284 
285     if (!isEnabled(o))
286         flags |= wxCONTROL_DISABLED;
287 
288     ControlPart part = o->style()->appearance();
289     if (supportsFocus(part) && isFocused(o))
290         flags |= wxCONTROL_FOCUSED;
291 
292     if (isPressed(o))
293         flags |= wxCONTROL_PRESSED;
294 
295     if (part == PushButtonPart || part == ButtonPart)
296         wxRendererNative::Get().DrawPushButton(window, *dc, rect, flags);
297     else if(part == RadioPart) {
298         if (isChecked(o))
299             flags |= wxCONTROL_CHECKED;
300 #if wxCHECK_VERSION(2,9,1)
301         wxRendererNative::Get().DrawRadioBitmap(window, *dc, rect, flags);
302 #elif wxCHECK_VERSION(2,9,0)
303         wxRendererNative::Get().DrawRadioButton(window, *dc, rect, flags);
304 #else
305         wxRenderer_DrawRadioButton(window, *dc, rect, flags);
306 #endif
307     }
308     else if(part == CheckboxPart) {
309         if (isChecked(o))
310             flags |= wxCONTROL_CHECKED;
311         wxRendererNative::Get().DrawCheckBox(window, *dc, rect, flags);
312     }
313     return false;
314 }
315 
adjustTextFieldStyle(CSSStyleSelector *,RenderStyle * style,Element *) const316 void RenderThemeWx::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
317 {
318 
319 }
320 
paintTextField(RenderObject * o,const RenderObject::PaintInfo & i,const IntRect & r)321 bool RenderThemeWx::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
322 {
323     wxWindow* window = nativeWindowForRenderObject(o);
324     wxDC* dc = static_cast<wxDC*>(i.context->platformContext());
325 #if wxCHECK_VERSION(2,9,0)
326     wxRendererNative::Get().DrawTextCtrl(window, *dc, r, 0);
327 #else
328     wxRenderer_DrawTextCtrl(window, *dc, r, 0);
329 #endif
330 
331     return false;
332 }
333 
minimumMenuListSize(RenderStyle *) const334 int RenderThemeWx::minimumMenuListSize(RenderStyle*) const
335 {
336     return MINIMUM_MENU_LIST_SIZE;
337 }
338 
adjustMenuListStyle(CSSStyleSelector *,RenderStyle * style,Element *) const339 void RenderThemeWx::adjustMenuListStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
340 {
341 }
342 
paintMenuList(RenderObject * o,const RenderObject::PaintInfo & i,const IntRect & r)343 bool RenderThemeWx::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
344 {
345     wxWindow* window = nativeWindowForRenderObject(o);
346     wxDC* dc = static_cast<wxDC*>(i.context->platformContext());
347 
348     int flags = 0;
349     if (!isEnabled(o))
350         flags |= wxCONTROL_DISABLED;
351 
352     if (supportsFocus(o->style()->appearance()) && isFocused(o))
353         flags |= wxCONTROL_FOCUSED;
354 
355     if (isPressed(o))
356         flags |= wxCONTROL_PRESSED;
357 
358 #if wxCHECK_VERSION(2,9,0)
359     wxRendererNative::Get().DrawChoice(window, *dc, r, flags);
360 #else
361     wxRenderer_DrawChoice(window, *dc, r, flags);
362 #endif
363 
364     return false;
365 }
366 
adjustMenuListButtonStyle(CSSStyleSelector *,RenderStyle *,Element *) const367 void RenderThemeWx::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
368 {
369     notImplemented();
370 }
371 
paintMenuListButton(RenderObject * o,const RenderObject::PaintInfo & i,const IntRect & r)372 bool RenderThemeWx::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
373 {
374     wxWindow* window = nativeWindowForRenderObject(o);
375     wxDC* dc = static_cast<wxDC*>(i.context->platformContext());
376 
377     int flags = 0;
378     if (!isEnabled(o))
379         flags |= wxCONTROL_DISABLED;
380 
381     if (supportsFocus(o->style()->appearance()) && isFocused(o))
382         flags |= wxCONTROL_FOCUSED;
383 
384     if (isPressed(o))
385         flags |= wxCONTROL_PRESSED;
386 
387     wxRendererNative::Get().DrawComboBoxDropButton(window, *dc, r, flags);
388 
389     return false;
390 }
391 
392 
platformActiveSelectionBackgroundColor() const393 Color RenderThemeWx::platformActiveSelectionBackgroundColor() const
394 {
395     return wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
396 }
397 
platformInactiveSelectionBackgroundColor() const398 Color RenderThemeWx::platformInactiveSelectionBackgroundColor() const
399 {
400     return wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW);
401 }
402 
platformActiveSelectionForegroundColor() const403 Color RenderThemeWx::platformActiveSelectionForegroundColor() const
404 {
405     // FIXME: Get wx to return the correct value for each platform.
406 #if __WXMAC__
407     return Color();
408 #else
409     return Color(255, 255, 255);
410 #endif
411 }
412 
platformInactiveSelectionForegroundColor() const413 Color RenderThemeWx::platformInactiveSelectionForegroundColor() const
414 {
415 #if __WXMAC__
416     return Color();
417 #else
418     return Color(255, 255, 255);
419 #endif
420 }
421 
popupInternalPaddingLeft(RenderStyle *) const422 int RenderThemeWx::popupInternalPaddingLeft(RenderStyle*) const
423 {
424     return POPUP_INTERNAL_PADDING_LEFT;
425 }
426 
popupInternalPaddingRight(RenderStyle *) const427 int RenderThemeWx::popupInternalPaddingRight(RenderStyle*) const
428 {
429     return POPUP_INTERNAL_PADDING_RIGHT;
430 }
431 
popupInternalPaddingTop(RenderStyle *) const432 int RenderThemeWx::popupInternalPaddingTop(RenderStyle*) const
433 {
434     return POPUP_INTERNAL_PADDING_TOP;
435 }
436 
popupInternalPaddingBottom(RenderStyle *) const437 int RenderThemeWx::popupInternalPaddingBottom(RenderStyle*) const
438 {
439     return POPUP_INTERNAL_PADDING_BOTTOM;
440 }
441 
442 }
443 
444