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