[wx] Enable wxWebKit to run using the wxGC Cairo backend on platforms other than...
[WebKit-https.git] / Source / WebCore / platform / wx / RenderThemeWx.cpp
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 "LocalDC.h"
34 #include "NotImplemented.h"
35 #include "PaintInfo.h"
36 #include "RenderView.h"
37
38 #include <wx/defs.h>
39
40 #include <wx/dc.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>
46
47 namespace WebCore {
48
49 class RenderThemeWx : public RenderTheme {
50 private:
51     RenderThemeWx() : RenderTheme() { }
52     virtual ~RenderThemeWx();
53
54 public:
55     static PassRefPtr<RenderTheme> create();
56
57     // A method asking if the theme's controls actually care about redrawing when hovered.
58     virtual bool supportsHover(const RenderStyle*) const { return true; }
59
60     virtual bool paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& r)
61     {
62         return paintButton(o, i, r);
63     }
64  
65     virtual void setCheckboxSize(RenderStyle*) const;
66
67     virtual bool paintRadio(RenderObject* o, const PaintInfo& i, const IntRect& r)
68     {
69         return paintButton(o, i, r);
70     }
71
72     virtual void setRadioSize(RenderStyle*) const;
73
74     virtual void adjustRepaintRect(const RenderObject*, IntRect&);
75
76     virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
77     virtual bool paintButton(RenderObject*, const PaintInfo&, const IntRect&);
78
79     virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
80     virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&);
81
82     virtual int minimumMenuListSize(RenderStyle*) const;
83
84     virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
85     virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&);
86
87     virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
88     virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
89
90     virtual bool isControlStyled(const RenderStyle*, const BorderData&,
91                                  const FillLayer&, const Color&) const;
92
93     virtual bool controlSupportsTints(const RenderObject*) const;
94
95     virtual void systemFont(int propId, FontDescription&) const;
96
97     virtual Color platformActiveSelectionBackgroundColor() const;
98     virtual Color platformInactiveSelectionBackgroundColor() const;
99     
100     virtual Color platformActiveSelectionForegroundColor() const;
101     virtual Color platformInactiveSelectionForegroundColor() const;
102     
103     virtual int popupInternalPaddingLeft(RenderStyle*) const;
104     virtual int popupInternalPaddingRight(RenderStyle*) const;
105     virtual int popupInternalPaddingTop(RenderStyle*) const;
106     virtual int popupInternalPaddingBottom(RenderStyle*) const;
107
108 private:
109     void addIntrinsicMargins(RenderStyle*) const;
110     void close();
111
112     bool supportsFocus(ControlPart) const;
113 };
114
115
116 // Constants
117
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
122
123 #ifdef __WXMAC__
124 #define POPUP_INTERNAL_PADDING_RIGHT 22
125 #else
126 #define POPUP_INTERNAL_PADDING_RIGHT 20
127 #endif
128
129 RenderThemeWx::~RenderThemeWx()
130 {
131 }
132
133 PassRefPtr<RenderTheme> RenderThemeWx::create()
134 {
135     return adoptRef(new RenderThemeWx());
136 }
137
138 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
139 {
140     static RenderTheme* rt = RenderThemeWx::create().releaseRef();
141     return rt;
142 }
143
144 wxWindow* nativeWindowForRenderObject(RenderObject* o)
145 {
146     FrameView* frameView = o->view()->frameView();
147     ASSERT(frameView);
148     ASSERT(frameView->hostWindow());
149     return frameView->hostWindow()->platformPageClient();
150 }
151
152
153 bool RenderThemeWx::isControlStyled(const RenderStyle* style, const BorderData& border,
154                                      const FillLayer& background, const Color& backgroundColor) const
155 {
156     if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart)
157         return style->border() != border;
158
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.
164     return false;
165 }
166
167 void RenderThemeWx::adjustRepaintRect(const RenderObject* o, IntRect& r)
168 {
169     switch (o->style()->appearance()) {
170         case MenulistPart: {
171             r.setWidth(r.width() + 100);
172             break;
173         }
174         default:
175             break;
176     }
177 }
178
179 bool RenderThemeWx::controlSupportsTints(const RenderObject* o) const
180 {
181     if (!isEnabled(o))
182         return false;
183
184     // Checkboxes only have tint when checked.
185     if (o->style()->appearance() == CheckboxPart)
186         return isChecked(o);
187
188     // For now assume other controls have tint if enabled.
189     return true;
190 }
191
192 void RenderThemeWx::systemFont(int propId, FontDescription& fontDescription) const
193 {
194     // no-op
195 }
196
197 void RenderThemeWx::addIntrinsicMargins(RenderStyle* style) const
198 {
199     // Cut out the intrinsic margins completely if we end up using a small font size
200     if (style->fontSize() < 11)
201         return;
202
203     // Intrinsic margin value.
204     const int m = 2;
205
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));
210
211         if (style->marginRight().quirk())
212             style->setMarginRight(Length(m, Fixed));
213     }
214
215     if (style->height().isAuto()) {
216         if (style->marginTop().quirk())
217             style->setMarginTop(Length(m, Fixed));
218
219         if (style->marginBottom().quirk())
220             style->setMarginBottom(Length(m, Fixed));
221     }
222 }
223
224 void RenderThemeWx::setCheckboxSize(RenderStyle* style) const
225 {
226     // If the width and height are both specified, then we have nothing to do.
227     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
228         return;
229
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
233     // metrics.
234     if (style->width().isIntrinsicOrAuto())
235         style->setWidth(Length(13, Fixed));
236
237     if (style->height().isAuto())
238         style->setHeight(Length(13, Fixed));
239 }
240
241 void RenderThemeWx::setRadioSize(RenderStyle* style) const
242 {
243     // This is the same as checkboxes.
244     setCheckboxSize(style);
245 }
246
247 bool RenderThemeWx::supportsFocus(ControlPart part) const
248 {
249     switch (part) {
250         case PushButtonPart:
251         case ButtonPart:
252         case TextFieldPart:
253         case MenulistPart:
254             return true;
255         default: // No for all others...
256             return false;
257     }
258 }
259
260 void RenderThemeWx::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
261 {
262     addIntrinsicMargins(style);
263 }
264
265 bool RenderThemeWx::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& r)
266 {
267     wxWindow* window = nativeWindowForRenderObject(o);
268     wxDC* dc = static_cast<wxDC*>(i.context->platformContext());
269     LocalDC localDC(dc, r);
270
271     int flags = 0;
272     
273     IntRect rect = r;
274
275     if (!isEnabled(o))
276         flags |= wxCONTROL_DISABLED;
277
278     ControlPart part = o->style()->appearance();
279     if (supportsFocus(part) && isFocused(o))
280         flags |= wxCONTROL_FOCUSED;
281
282     if (isPressed(o))
283         flags |= wxCONTROL_PRESSED;
284     
285     if (part == PushButtonPart || part == ButtonPart)
286         wxRendererNative::Get().DrawPushButton(window, *localDC.context(), rect, flags);
287     else if(part == RadioPart) {
288         if (isChecked(o))
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);
294 #else
295         wxRenderer_DrawRadioButton(window, *localDC.context(), rect, flags);
296 #endif
297     }
298     else if(part == CheckboxPart) {
299         if (isChecked(o))
300             flags |= wxCONTROL_CHECKED;
301         wxRendererNative::Get().DrawCheckBox(window, *localDC.context(), rect, flags);
302     }
303     return false;
304 }
305
306 void RenderThemeWx::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
307 {
308
309 }
310
311 bool RenderThemeWx::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& r)
312 {
313     wxWindow* window = nativeWindowForRenderObject(o);
314     wxDC* dc = static_cast<wxDC*>(i.context->platformContext());
315     LocalDC localDC(dc, r);
316     int flags = 0;
317     
318     IntRect rect = r;
319
320     ControlPart part = o->style()->appearance();
321     if (supportsFocus(part) && isFocused(o))
322         flags |= wxCONTROL_FOCUSED;
323
324 #if wxCHECK_VERSION(2,9,0)
325     wxRendererNative::Get().DrawTextCtrl(window, *localDC.context(), rect, flags);
326 #else
327     wxRenderer_DrawTextCtrl(window, *localDC.context(), r, 0);
328 #endif
329
330     return false;
331 }
332
333 int RenderThemeWx::minimumMenuListSize(RenderStyle*) const 
334
335     return MINIMUM_MENU_LIST_SIZE; 
336 }
337
338 void RenderThemeWx::adjustMenuListStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
339 {
340      style->resetBorder();
341
342     // Height is locked to auto.
343     style->setHeight(Length(Auto));
344     
345     style->setPaddingTop(Length(2, Fixed));
346     style->setPaddingBottom(Length(2, Fixed));
347 }
348     
349 bool RenderThemeWx::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& r)
350 {
351     wxWindow* window = nativeWindowForRenderObject(o);
352     wxDC* dc = static_cast<wxDC*>(i.context->platformContext());
353
354     LocalDC localDC(dc, r);
355     IntRect rect = r;
356
357     int flags = 0;      
358     if (!isEnabled(o))
359         flags |= wxCONTROL_DISABLED;
360         
361     if (supportsFocus(o->style()->appearance()) && isFocused(o))
362         flags |= wxCONTROL_FOCUSED;
363
364     if (isPressed(o))
365         flags |= wxCONTROL_PRESSED;
366
367 #if wxCHECK_VERSION(2,9,0)
368     wxRendererNative::Get().DrawChoice(window, *localDC.context(), rect, flags);
369 #else
370     wxRenderer_DrawChoice(window, *localDC.context(), rect, flags);
371 #endif
372
373     return false;
374 }
375
376 void RenderThemeWx::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
377 {
378     notImplemented();
379 }
380     
381 bool RenderThemeWx::paintMenuListButton(RenderObject* o, const PaintInfo& i, const IntRect& r)
382 {
383     wxWindow* window = nativeWindowForRenderObject(o);
384     wxDC* dc = static_cast<wxDC*>(i.context->platformContext());
385     LocalDC localDC(dc, r);
386     IntRect rect = r;
387
388     int flags = 0;      
389     if (!isEnabled(o))
390         flags |= wxCONTROL_DISABLED;
391         
392     if (supportsFocus(o->style()->appearance()) && isFocused(o))
393         flags |= wxCONTROL_FOCUSED;
394     
395     if (isPressed(o))
396         flags |= wxCONTROL_PRESSED;
397
398     wxRendererNative::Get().DrawComboBoxDropButton(window, *localDC.context(), rect, flags);
399             
400     return false;
401 }
402
403     
404 Color RenderThemeWx::platformActiveSelectionBackgroundColor() const
405 {
406     return wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
407 }
408
409 Color RenderThemeWx::platformInactiveSelectionBackgroundColor() const
410 {
411     return wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW);
412 }
413
414 Color RenderThemeWx::platformActiveSelectionForegroundColor() const
415 {
416     // FIXME: Get wx to return the correct value for each platform.
417 #if __WXMAC__
418     return Color();
419 #else
420     return Color(255, 255, 255);
421 #endif
422 }
423
424 Color RenderThemeWx::platformInactiveSelectionForegroundColor() const
425 {
426 #if __WXMAC__
427     return Color();
428 #else
429     return Color(255, 255, 255);
430 #endif
431 }
432
433 int RenderThemeWx::popupInternalPaddingLeft(RenderStyle*) const 
434
435     return POPUP_INTERNAL_PADDING_LEFT; 
436 }
437
438 int RenderThemeWx::popupInternalPaddingRight(RenderStyle*) const 
439 {
440     return POPUP_INTERNAL_PADDING_RIGHT;
441 }
442
443 int RenderThemeWx::popupInternalPaddingTop(RenderStyle*) const 
444 {
445     return POPUP_INTERNAL_PADDING_TOP;
446 }
447
448 int RenderThemeWx::popupInternalPaddingBottom(RenderStyle*) const
449
450     return POPUP_INTERNAL_PADDING_BOTTOM; 
451 }
452
453 }
454