From 10ba26777d58f8e7898182e5a98087ccac7ebedd Mon Sep 17 00:00:00 2001 From: Jaakko Salli Date: Sun, 20 Mar 2011 10:59:22 +0000 Subject: [PATCH] Redone (generic) wxComboCtrl background painting and handling. The 'actual' wxWindow background colour is now largely ignored and overridden to refer the text-area's background colour instead (as is usually the case with controls like this). Base 'transparent' background is now only painted when double-buffered rendering is required, and otherwise delegated to the system, as appropriate. This should significantly improve control's appearance and compliancy with GTK+ and OS X themes and custom backgrounds. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@67255 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/combo.h | 6 +++++ include/wx/generic/combo.h | 17 ++++++++++++ src/common/combocmn.cpp | 48 ++++++++++++++++++++------------- src/generic/combog.cpp | 67 ++++++++++++++++++++++++++++------------------ 4 files changed, 93 insertions(+), 45 deletions(-) diff --git a/include/wx/combo.h b/include/wx/combo.h index 9c38cda..fe70aaa 100644 --- a/include/wx/combo.h +++ b/include/wx/combo.h @@ -445,6 +445,9 @@ public: // Return true if Create has finished bool IsCreated() const { return m_iFlags & wxCC_IFLAG_CREATED ? true : false; } + // Need to override to return text area background colour + wxColour GetBackgroundColour() const; + // common code to be called on popup hide/dismiss void OnPopupDismiss(bool generateEvent); @@ -671,6 +674,9 @@ protected: wxRect m_tcArea; wxRect m_btnArea; + // Colour of the the text area, in case m_text is NULL + wxColour m_tcBgCol; + // current button state (uses renderer flags) int m_btnState; diff --git a/include/wx/generic/combo.h b/include/wx/generic/combo.h index 34eead1..b25325c 100644 --- a/include/wx/generic/combo.h +++ b/include/wx/generic/combo.h @@ -31,6 +31,8 @@ #endif +#include "wx/dcbuffer.h" + extern WXDLLIMPEXP_DATA_CORE(const char) wxComboBoxNameStr[]; class WXDLLIMPEXP_CORE wxGenericComboCtrl : public wxComboCtrlBase @@ -96,6 +98,21 @@ protected: virtual WXHWND GetEditHWND() const { return NULL; } #endif + // For better transparent background rendering + virtual bool HasTransparentBackground() + { + #if wxALWAYS_NATIVE_DOUBLE_BUFFER + #ifdef __WXGTK__ + // Sanity check for GTK+ + return IsDoubleBuffered(); + #else + return true; + #endif + #else + return false; + #endif + } + // Mandatory virtuals virtual void OnResize(); diff --git a/src/common/combocmn.cpp b/src/common/combocmn.cpp index ccabb72..2ff10a3 100644 --- a/src/common/combocmn.cpp +++ b/src/common/combocmn.cpp @@ -1071,29 +1071,31 @@ wxComboCtrlBase::CreateTextCtrl(int style) void wxComboCtrlBase::OnThemeChange() { - // Leave the default bg on the Mac so the area used by the focus ring will - // be the correct colour and themed brush. Instead we'll use - // wxSYS_COLOUR_WINDOW in the EVT_PAINT handler as needed. -#ifndef __WXMAC__ - #if defined(__WXMSW__) || defined(__WXGTK__) + // Because wxComboCtrl has transparent parts on most platforms, we + // don't want to touch the actual background colour. Instead, we just + // usually re-obtain m_tcBgCol here. + +#if defined(__WXMSW__) || defined(__WXGTK__) wxVisualAttributes vattrs = wxComboBox::GetClassDefaultAttributes(); - #else +#else wxVisualAttributes vattrs; vattrs.colFg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); vattrs.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - #endif +#endif + + if ( !m_hasBgCol ) + m_tcBgCol = vattrs.colBg; +#ifndef __WXMAC__ // Only change the colours if application has not specified // custom ones. if ( !m_hasFgCol ) { SetOwnForegroundColour(vattrs.colFg); - m_hasFgCol = false; } - if ( !m_hasBgCol ) + if ( !HasTransparentBackground() ) { - SetOwnBackgroundColour(vattrs.colBg); - m_hasBgCol = false; + SetOwnBackgroundColour(GetParent()->GetBackgroundColour()); } #endif // !__WXMAC__ } @@ -1478,14 +1480,20 @@ bool wxComboCtrlBase::SetForegroundColour(const wxColour& colour) bool wxComboCtrlBase::SetBackgroundColour(const wxColour& colour) { - if ( wxControl::SetBackgroundColour(colour) ) - { - if ( m_text ) - m_text->SetBackgroundColour(colour); - return true; - } - return false; + if ( m_text ) + m_text->SetBackgroundColour(colour); + m_tcBgCol = colour; + m_hasBgCol = true; + return true; } + +wxColour wxComboCtrlBase::GetBackgroundColour() const +{ + if ( m_text ) + return m_text->GetBackgroundColour(); + return m_tcBgCol; +} + // ---------------------------------------------------------------------------- // painting // ---------------------------------------------------------------------------- @@ -1644,7 +1652,9 @@ void wxComboCtrlBase::DrawButton( wxDC& dc, const wxRect& rect, int flags ) return; // Need to clear button background even if m_btn is present - if ( flags & Button_PaintBackground ) + if ( (flags & Button_PaintBackground) && + (!HasTransparentBackground() || + !(m_iFlags & wxCC_IFLAG_BUTTON_OUTSIDE)) ) { wxColour bgCol; diff --git a/src/generic/combog.cpp b/src/generic/combog.cpp index c70e9d4..be0fa44 100644 --- a/src/generic/combog.cpp +++ b/src/generic/combog.cpp @@ -201,8 +201,10 @@ bool wxGenericComboCtrl::Create(wxWindow *parent, // Add keyboard input handlers for main control and textctrl InstallInputHandlers(); - // Set background - SetBackgroundStyle( wxBG_STYLE_CUSTOM ); // for double-buffering + // Set background style for double-buffering, when needed + // (cannot use when system draws background automatically) + if ( !HasTransparentBackground() ) + SetBackgroundStyle( wxBG_STYLE_PAINT ); // SetInitialSize should be called last SetInitialSize(size); @@ -238,11 +240,19 @@ void wxGenericComboCtrl::OnResize() void wxGenericComboCtrl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) { - wxSize sz = GetClientSize(); - wxAutoBufferedPaintDC dc(this); + // Determine wxDC to use based on need to double-buffer or + // use system-generated transparent background portions + wxDC* dcPtr; + if ( HasTransparentBackground() ) + dcPtr = new wxPaintDC(this); + else + dcPtr = new wxAutoBufferedPaintDC(this); + wxDC& dc = *dcPtr; - const wxRect& rectb = m_btnArea; - wxRect rect = m_tcArea; + wxSize sz = GetClientSize(); + const wxRect& butRect = m_btnArea; + wxRect tcRect = m_tcArea; + wxRect fullRect(0, 0, sz.x, sz.y); // artificial simple border if ( m_widthCustomBorder ) @@ -256,10 +266,10 @@ void wxGenericComboCtrl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) dc.SetPen( pen1 ); // area around both controls - wxRect rect2(0,0,sz.x,sz.y); + wxRect rect2(fullRect); if ( m_iFlags & wxCC_IFLAG_BUTTON_OUTSIDE ) { - rect2 = m_tcArea; + rect2 = tcRect; if ( customBorder == 1 ) { rect2.Inflate(1); @@ -282,44 +292,49 @@ void wxGenericComboCtrl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) dc.DrawRectangle(rect2); } -#ifndef __WXMAC__ // see note in OnThemeChange - wxColour winCol = GetBackgroundColour(); -#else - wxColour winCol = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); -#endif - dc.SetBrush(winCol); - dc.SetPen(winCol); - - //wxLogDebug(wxT("hei: %i tcy: %i tchei: %i"),GetClientSize().y,m_tcArea.y,m_tcArea.height); - //wxLogDebug(wxT("btnx: %i tcx: %i tcwid: %i"),m_btnArea.x,m_tcArea.x,m_tcArea.width); + // Clear the main background if the system doesn't do it by itself + if ( !HasTransparentBackground() && + (tcRect.x > 0 || tcRect.y > 0) ) + { + wxColour winCol = GetParent()->GetBackgroundColour(); + dc.SetBrush(winCol); + dc.SetPen(winCol); - // clear main background - dc.DrawRectangle(rect); + dc.DrawRectangle(fullRect); + } if ( !m_btn ) { // Standard button rendering - DrawButton(dc,rectb); + DrawButton(dc, butRect); } // paint required portion on the control - if ( (!m_text || m_widthCustomPaint) ) + if ( !m_text || m_widthCustomPaint ) { wxASSERT( m_widthCustomPaint >= 0 ); + // Clear the text-control area background + wxColour tcCol = GetBackgroundColour(); + dc.SetBrush(tcCol); + dc.SetPen(tcCol); + dc.DrawRectangle(tcRect); + // this is intentionally here to allow drawed rectangle's // right edge to be hidden if ( m_text ) - rect.width = m_widthCustomPaint; + tcRect.width = m_widthCustomPaint; dc.SetFont( GetFont() ); - dc.SetClippingRegion(rect); + dc.SetClippingRegion(tcRect); if ( m_popupInterface ) - m_popupInterface->PaintComboControl(dc,rect); + m_popupInterface->PaintComboControl(dc, tcRect); else - wxComboPopup::DefaultPaintComboControl(this,dc,rect); + wxComboPopup::DefaultPaintComboControl(this, dc, tcRect); } + + delete dcPtr; } void wxGenericComboCtrl::OnMouseEvent( wxMouseEvent& event ) -- 2.7.4