| /* |
| * Copyright (C) 2007 Kevin Ollivier <kevino@theolliviers.com> |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "config.h" |
| #include "RenderTheme.h" |
| |
| #include "Document.h" |
| #include "FrameView.h" |
| #include "GraphicsContext.h" |
| #include "HostWindow.h" |
| #include "NotImplemented.h" |
| #include "PaintInfo.h" |
| #include "RenderView.h" |
| |
| #include <wx/defs.h> |
| |
| #include <wx/dc.h> |
| #include <wx/dcgraph.h> |
| #include <wx/renderer.h> |
| #include <wx/dcclient.h> |
| #include <wx/scrolwin.h> |
| #include <wx/settings.h> |
| |
| namespace WebCore { |
| |
| class RenderThemeWx : public RenderTheme { |
| private: |
| RenderThemeWx() : RenderTheme() { } |
| virtual ~RenderThemeWx(); |
| |
| public: |
| static PassRefPtr<RenderTheme> create(); |
| |
| // A method asking if the theme's controls actually care about redrawing when hovered. |
| virtual bool supportsHover(const RenderStyle*) const { return true; } |
| |
| virtual bool paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& r) |
| { |
| return paintButton(o, i, r); |
| } |
| |
| virtual void setCheckboxSize(RenderStyle*) const; |
| |
| virtual bool paintRadio(RenderObject* o, const PaintInfo& i, const IntRect& r) |
| { |
| return paintButton(o, i, r); |
| } |
| |
| virtual void setRadioSize(RenderStyle*) const; |
| |
| virtual void adjustRepaintRect(const RenderObject*, IntRect&); |
| |
| virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; |
| virtual bool paintButton(RenderObject*, const PaintInfo&, const IntRect&); |
| |
| virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const; |
| virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&); |
| |
| virtual int minimumMenuListSize(RenderStyle*) const; |
| |
| virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const; |
| virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&); |
| |
| virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; |
| virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&); |
| |
| virtual bool isControlStyled(const RenderStyle*, const BorderData&, |
| const FillLayer&, const Color&) const; |
| |
| virtual bool controlSupportsTints(const RenderObject*) const; |
| |
| virtual void systemFont(int propId, FontDescription&) const; |
| |
| virtual Color platformActiveSelectionBackgroundColor() const; |
| virtual Color platformInactiveSelectionBackgroundColor() const; |
| |
| virtual Color platformActiveSelectionForegroundColor() const; |
| virtual Color platformInactiveSelectionForegroundColor() const; |
| |
| virtual int popupInternalPaddingLeft(RenderStyle*) const; |
| virtual int popupInternalPaddingRight(RenderStyle*) const; |
| virtual int popupInternalPaddingTop(RenderStyle*) const; |
| virtual int popupInternalPaddingBottom(RenderStyle*) const; |
| |
| private: |
| void addIntrinsicMargins(RenderStyle*) const; |
| void close(); |
| |
| bool supportsFocus(ControlPart) const; |
| }; |
| |
| |
| // Constants |
| |
| #define MINIMUM_MENU_LIST_SIZE 21 |
| #define POPUP_INTERNAL_PADDING_LEFT 6 |
| #define POPUP_INTERNAL_PADDING_TOP 2 |
| #define POPUP_INTERNAL_PADDING_BOTTOM 2 |
| |
| #ifdef __WXMAC__ |
| #define POPUP_INTERNAL_PADDING_RIGHT 22 |
| #else |
| #define POPUP_INTERNAL_PADDING_RIGHT 20 |
| #endif |
| |
| RenderThemeWx::~RenderThemeWx() |
| { |
| } |
| |
| PassRefPtr<RenderTheme> RenderThemeWx::create() |
| { |
| return adoptRef(new RenderThemeWx()); |
| } |
| |
| PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page) |
| { |
| static RenderTheme* rt = RenderThemeWx::create().releaseRef(); |
| return rt; |
| } |
| |
| wxWindow* nativeWindowForRenderObject(RenderObject* o) |
| { |
| FrameView* frameView = o->view()->frameView(); |
| ASSERT(frameView); |
| ASSERT(frameView->hostWindow()); |
| return frameView->hostWindow()->platformPageClient(); |
| } |
| |
| |
| bool RenderThemeWx::isControlStyled(const RenderStyle* style, const BorderData& border, |
| const FillLayer& background, const Color& backgroundColor) const |
| { |
| if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart) |
| return style->border() != border; |
| |
| // Normally CSS can be used to set properties of form controls (such as adding a background bitmap). |
| // However, for this to work RenderThemeWx needs to adjust uncustomized elements (e.g. buttons) to reflect the |
| // changes made by CSS. Since we don't do that right now, the native parts of form elements appear in odd places. |
| // Until we have time to implement that support, we return false here, so that we ignore customizations |
| // and always use the native theme drawing to draw form controls. |
| return false; |
| } |
| |
| void RenderThemeWx::adjustRepaintRect(const RenderObject* o, IntRect& r) |
| { |
| switch (o->style()->appearance()) { |
| case MenulistPart: { |
| r.setWidth(r.width() + 100); |
| break; |
| } |
| default: |
| break; |
| } |
| } |
| |
| bool RenderThemeWx::controlSupportsTints(const RenderObject* o) const |
| { |
| if (!isEnabled(o)) |
| return false; |
| |
| // Checkboxes only have tint when checked. |
| if (o->style()->appearance() == CheckboxPart) |
| return isChecked(o); |
| |
| // For now assume other controls have tint if enabled. |
| return true; |
| } |
| |
| void RenderThemeWx::systemFont(int propId, FontDescription& fontDescription) const |
| { |
| // no-op |
| } |
| |
| void RenderThemeWx::addIntrinsicMargins(RenderStyle* style) const |
| { |
| // Cut out the intrinsic margins completely if we end up using a small font size |
| if (style->fontSize() < 11) |
| return; |
| |
| // Intrinsic margin value. |
| const int m = 2; |
| |
| // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed. |
| if (style->width().isIntrinsicOrAuto()) { |
| if (style->marginLeft().quirk()) |
| style->setMarginLeft(Length(m, Fixed)); |
| |
| if (style->marginRight().quirk()) |
| style->setMarginRight(Length(m, Fixed)); |
| } |
| |
| if (style->height().isAuto()) { |
| if (style->marginTop().quirk()) |
| style->setMarginTop(Length(m, Fixed)); |
| |
| if (style->marginBottom().quirk()) |
| style->setMarginBottom(Length(m, Fixed)); |
| } |
| } |
| |
| void RenderThemeWx::setCheckboxSize(RenderStyle* style) const |
| { |
| // If the width and height are both specified, then we have nothing to do. |
| if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) |
| return; |
| |
| // FIXME: A hard-coded size of 13 is used. This is wrong but necessary for now. It matches Firefox. |
| // At different DPI settings on Windows, querying the theme gives you a larger size that accounts for |
| // the higher DPI. Until our entire engine honors a DPI setting other than 96, we can't rely on the theme's |
| // metrics. |
| if (style->width().isIntrinsicOrAuto()) |
| style->setWidth(Length(13, Fixed)); |
| |
| if (style->height().isAuto()) |
| style->setHeight(Length(13, Fixed)); |
| } |
| |
| void RenderThemeWx::setRadioSize(RenderStyle* style) const |
| { |
| // This is the same as checkboxes. |
| setCheckboxSize(style); |
| } |
| |
| bool RenderThemeWx::supportsFocus(ControlPart part) const |
| { |
| switch (part) { |
| case PushButtonPart: |
| case ButtonPart: |
| case TextFieldPart: |
| return true; |
| default: // No for all others... |
| return false; |
| } |
| } |
| |
| void RenderThemeWx::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const |
| { |
| addIntrinsicMargins(style); |
| } |
| |
| bool RenderThemeWx::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& r) |
| { |
| wxWindow* window = nativeWindowForRenderObject(o); |
| wxDC* dc = static_cast<wxDC*>(i.context->platformContext()); |
| int flags = 0; |
| |
| IntRect rect = r; |
| |
| // On Mac, wxGraphicsContext and wxDC share the same native implementation, |
| // and so transformations are available. |
| // On Win and Linux, however, this is not true and transforms are lost, |
| // so we need to restore them here. |
| #if USE(WXGC) && !defined(__WXMAC__) |
| double xtrans = 0; |
| double ytrans = 0; |
| |
| wxGCDC* gcdc = static_cast<wxGCDC*>(dc); |
| wxGraphicsContext* gc = gcdc->GetGraphicsContext(); |
| gc->GetTransform().TransformPoint(&xtrans, &ytrans); |
| rect.setX(r.x() + (int)xtrans); |
| rect.setY(r.y() + (int)ytrans); |
| #endif |
| |
| if (!isEnabled(o)) |
| flags |= wxCONTROL_DISABLED; |
| |
| ControlPart part = o->style()->appearance(); |
| if (supportsFocus(part) && isFocused(o)) |
| flags |= wxCONTROL_FOCUSED; |
| |
| if (isPressed(o)) |
| flags |= wxCONTROL_PRESSED; |
| |
| if (part == PushButtonPart || part == ButtonPart) |
| wxRendererNative::Get().DrawPushButton(window, *dc, rect, flags); |
| else if(part == RadioPart) { |
| if (isChecked(o)) |
| flags |= wxCONTROL_CHECKED; |
| #if wxCHECK_VERSION(2,9,1) |
| wxRendererNative::Get().DrawRadioBitmap(window, *dc, rect, flags); |
| #elif wxCHECK_VERSION(2,9,0) |
| wxRendererNative::Get().DrawRadioButton(window, *dc, rect, flags); |
| #else |
| wxRenderer_DrawRadioButton(window, *dc, rect, flags); |
| #endif |
| } |
| else if(part == CheckboxPart) { |
| if (isChecked(o)) |
| flags |= wxCONTROL_CHECKED; |
| wxRendererNative::Get().DrawCheckBox(window, *dc, rect, flags); |
| } |
| return false; |
| } |
| |
| void RenderThemeWx::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const |
| { |
| |
| } |
| |
| bool RenderThemeWx::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& r) |
| { |
| wxWindow* window = nativeWindowForRenderObject(o); |
| wxDC* dc = static_cast<wxDC*>(i.context->platformContext()); |
| #if wxCHECK_VERSION(2,9,0) |
| wxRendererNative::Get().DrawTextCtrl(window, *dc, r, 0); |
| #else |
| wxRenderer_DrawTextCtrl(window, *dc, r, 0); |
| #endif |
| |
| return false; |
| } |
| |
| int RenderThemeWx::minimumMenuListSize(RenderStyle*) const |
| { |
| return MINIMUM_MENU_LIST_SIZE; |
| } |
| |
| void RenderThemeWx::adjustMenuListStyle(CSSStyleSelector*, RenderStyle* style, Element*) const |
| { |
| } |
| |
| bool RenderThemeWx::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& r) |
| { |
| wxWindow* window = nativeWindowForRenderObject(o); |
| wxDC* dc = static_cast<wxDC*>(i.context->platformContext()); |
| |
| int flags = 0; |
| if (!isEnabled(o)) |
| flags |= wxCONTROL_DISABLED; |
| |
| if (supportsFocus(o->style()->appearance()) && isFocused(o)) |
| flags |= wxCONTROL_FOCUSED; |
| |
| if (isPressed(o)) |
| flags |= wxCONTROL_PRESSED; |
| |
| #if wxCHECK_VERSION(2,9,0) |
| wxRendererNative::Get().DrawChoice(window, *dc, r, flags); |
| #else |
| wxRenderer_DrawChoice(window, *dc, r, flags); |
| #endif |
| |
| return false; |
| } |
| |
| void RenderThemeWx::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const |
| { |
| notImplemented(); |
| } |
| |
| bool RenderThemeWx::paintMenuListButton(RenderObject* o, const PaintInfo& i, const IntRect& r) |
| { |
| wxWindow* window = nativeWindowForRenderObject(o); |
| wxDC* dc = static_cast<wxDC*>(i.context->platformContext()); |
| |
| int flags = 0; |
| if (!isEnabled(o)) |
| flags |= wxCONTROL_DISABLED; |
| |
| if (supportsFocus(o->style()->appearance()) && isFocused(o)) |
| flags |= wxCONTROL_FOCUSED; |
| |
| if (isPressed(o)) |
| flags |= wxCONTROL_PRESSED; |
| |
| wxRendererNative::Get().DrawComboBoxDropButton(window, *dc, r, flags); |
| |
| return false; |
| } |
| |
| |
| Color RenderThemeWx::platformActiveSelectionBackgroundColor() const |
| { |
| return wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT); |
| } |
| |
| Color RenderThemeWx::platformInactiveSelectionBackgroundColor() const |
| { |
| return wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW); |
| } |
| |
| Color RenderThemeWx::platformActiveSelectionForegroundColor() const |
| { |
| // FIXME: Get wx to return the correct value for each platform. |
| #if __WXMAC__ |
| return Color(); |
| #else |
| return Color(255, 255, 255); |
| #endif |
| } |
| |
| Color RenderThemeWx::platformInactiveSelectionForegroundColor() const |
| { |
| #if __WXMAC__ |
| return Color(); |
| #else |
| return Color(255, 255, 255); |
| #endif |
| } |
| |
| int RenderThemeWx::popupInternalPaddingLeft(RenderStyle*) const |
| { |
| return POPUP_INTERNAL_PADDING_LEFT; |
| } |
| |
| int RenderThemeWx::popupInternalPaddingRight(RenderStyle*) const |
| { |
| return POPUP_INTERNAL_PADDING_RIGHT; |
| } |
| |
| int RenderThemeWx::popupInternalPaddingTop(RenderStyle*) const |
| { |
| return POPUP_INTERNAL_PADDING_TOP; |
| } |
| |
| int RenderThemeWx::popupInternalPaddingBottom(RenderStyle*) const |
| { |
| return POPUP_INTERNAL_PADDING_BOTTOM; |
| } |
| |
| } |
| |