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
This commit is contained in:
Jaakko Salli
2011-03-20 10:59:22 +00:00
parent 80fdcdb90e
commit 10ba26777d
4 changed files with 93 additions and 45 deletions

View File

@@ -445,6 +445,9 @@ public:
// Return true if Create has finished // Return true if Create has finished
bool IsCreated() const { return m_iFlags & wxCC_IFLAG_CREATED ? true : false; } 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 // common code to be called on popup hide/dismiss
void OnPopupDismiss(bool generateEvent); void OnPopupDismiss(bool generateEvent);
@@ -671,6 +674,9 @@ protected:
wxRect m_tcArea; wxRect m_tcArea;
wxRect m_btnArea; wxRect m_btnArea;
// Colour of the the text area, in case m_text is NULL
wxColour m_tcBgCol;
// current button state (uses renderer flags) // current button state (uses renderer flags)
int m_btnState; int m_btnState;

View File

@@ -31,6 +31,8 @@
#endif #endif
#include "wx/dcbuffer.h"
extern WXDLLIMPEXP_DATA_CORE(const char) wxComboBoxNameStr[]; extern WXDLLIMPEXP_DATA_CORE(const char) wxComboBoxNameStr[];
class WXDLLIMPEXP_CORE wxGenericComboCtrl : public wxComboCtrlBase class WXDLLIMPEXP_CORE wxGenericComboCtrl : public wxComboCtrlBase
@@ -96,6 +98,21 @@ protected:
virtual WXHWND GetEditHWND() const { return NULL; } virtual WXHWND GetEditHWND() const { return NULL; }
#endif #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 // Mandatory virtuals
virtual void OnResize(); virtual void OnResize();

View File

@@ -1071,10 +1071,10 @@ wxComboCtrlBase::CreateTextCtrl(int style)
void wxComboCtrlBase::OnThemeChange() void wxComboCtrlBase::OnThemeChange()
{ {
// Leave the default bg on the Mac so the area used by the focus ring will // Because wxComboCtrl has transparent parts on most platforms, we
// be the correct colour and themed brush. Instead we'll use // don't want to touch the actual background colour. Instead, we just
// wxSYS_COLOUR_WINDOW in the EVT_PAINT handler as needed. // usually re-obtain m_tcBgCol here.
#ifndef __WXMAC__
#if defined(__WXMSW__) || defined(__WXGTK__) #if defined(__WXMSW__) || defined(__WXGTK__)
wxVisualAttributes vattrs = wxComboBox::GetClassDefaultAttributes(); wxVisualAttributes vattrs = wxComboBox::GetClassDefaultAttributes();
#else #else
@@ -1083,17 +1083,19 @@ void wxComboCtrlBase::OnThemeChange()
vattrs.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); 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 // Only change the colours if application has not specified
// custom ones. // custom ones.
if ( !m_hasFgCol ) if ( !m_hasFgCol )
{ {
SetOwnForegroundColour(vattrs.colFg); SetOwnForegroundColour(vattrs.colFg);
m_hasFgCol = false;
} }
if ( !m_hasBgCol ) if ( !HasTransparentBackground() )
{ {
SetOwnBackgroundColour(vattrs.colBg); SetOwnBackgroundColour(GetParent()->GetBackgroundColour());
m_hasBgCol = false;
} }
#endif // !__WXMAC__ #endif // !__WXMAC__
} }
@@ -1477,15 +1479,21 @@ bool wxComboCtrlBase::SetForegroundColour(const wxColour& colour)
} }
bool wxComboCtrlBase::SetBackgroundColour(const wxColour& colour) bool wxComboCtrlBase::SetBackgroundColour(const wxColour& colour)
{
if ( wxControl::SetBackgroundColour(colour) )
{ {
if ( m_text ) if ( m_text )
m_text->SetBackgroundColour(colour); m_text->SetBackgroundColour(colour);
m_tcBgCol = colour;
m_hasBgCol = true;
return true; return true;
} }
return false;
wxColour wxComboCtrlBase::GetBackgroundColour() const
{
if ( m_text )
return m_text->GetBackgroundColour();
return m_tcBgCol;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// painting // painting
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -1644,7 +1652,9 @@ void wxComboCtrlBase::DrawButton( wxDC& dc, const wxRect& rect, int flags )
return; return;
// Need to clear button background even if m_btn is present // 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; wxColour bgCol;

View File

@@ -201,8 +201,10 @@ bool wxGenericComboCtrl::Create(wxWindow *parent,
// Add keyboard input handlers for main control and textctrl // Add keyboard input handlers for main control and textctrl
InstallInputHandlers(); InstallInputHandlers();
// Set background // Set background style for double-buffering, when needed
SetBackgroundStyle( wxBG_STYLE_CUSTOM ); // for double-buffering // (cannot use when system draws background automatically)
if ( !HasTransparentBackground() )
SetBackgroundStyle( wxBG_STYLE_PAINT );
// SetInitialSize should be called last // SetInitialSize should be called last
SetInitialSize(size); SetInitialSize(size);
@@ -238,11 +240,19 @@ void wxGenericComboCtrl::OnResize()
void wxGenericComboCtrl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) void wxGenericComboCtrl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) )
{ {
wxSize sz = GetClientSize(); // Determine wxDC to use based on need to double-buffer or
wxAutoBufferedPaintDC dc(this); // 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; wxSize sz = GetClientSize();
wxRect rect = m_tcArea; const wxRect& butRect = m_btnArea;
wxRect tcRect = m_tcArea;
wxRect fullRect(0, 0, sz.x, sz.y);
// artificial simple border // artificial simple border
if ( m_widthCustomBorder ) if ( m_widthCustomBorder )
@@ -256,10 +266,10 @@ void wxGenericComboCtrl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) )
dc.SetPen( pen1 ); dc.SetPen( pen1 );
// area around both controls // area around both controls
wxRect rect2(0,0,sz.x,sz.y); wxRect rect2(fullRect);
if ( m_iFlags & wxCC_IFLAG_BUTTON_OUTSIDE ) if ( m_iFlags & wxCC_IFLAG_BUTTON_OUTSIDE )
{ {
rect2 = m_tcArea; rect2 = tcRect;
if ( customBorder == 1 ) if ( customBorder == 1 )
{ {
rect2.Inflate(1); rect2.Inflate(1);
@@ -282,44 +292,49 @@ void wxGenericComboCtrl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) )
dc.DrawRectangle(rect2); dc.DrawRectangle(rect2);
} }
#ifndef __WXMAC__ // see note in OnThemeChange // Clear the main background if the system doesn't do it by itself
wxColour winCol = GetBackgroundColour(); if ( !HasTransparentBackground() &&
#else (tcRect.x > 0 || tcRect.y > 0) )
wxColour winCol = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); {
#endif wxColour winCol = GetParent()->GetBackgroundColour();
dc.SetBrush(winCol); dc.SetBrush(winCol);
dc.SetPen(winCol); dc.SetPen(winCol);
//wxLogDebug(wxT("hei: %i tcy: %i tchei: %i"),GetClientSize().y,m_tcArea.y,m_tcArea.height); dc.DrawRectangle(fullRect);
//wxLogDebug(wxT("btnx: %i tcx: %i tcwid: %i"),m_btnArea.x,m_tcArea.x,m_tcArea.width); }
// clear main background
dc.DrawRectangle(rect);
if ( !m_btn ) if ( !m_btn )
{ {
// Standard button rendering // Standard button rendering
DrawButton(dc,rectb); DrawButton(dc, butRect);
} }
// paint required portion on the control // paint required portion on the control
if ( (!m_text || m_widthCustomPaint) ) if ( !m_text || m_widthCustomPaint )
{ {
wxASSERT( m_widthCustomPaint >= 0 ); 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 // this is intentionally here to allow drawed rectangle's
// right edge to be hidden // right edge to be hidden
if ( m_text ) if ( m_text )
rect.width = m_widthCustomPaint; tcRect.width = m_widthCustomPaint;
dc.SetFont( GetFont() ); dc.SetFont( GetFont() );
dc.SetClippingRegion(rect); dc.SetClippingRegion(tcRect);
if ( m_popupInterface ) if ( m_popupInterface )
m_popupInterface->PaintComboControl(dc,rect); m_popupInterface->PaintComboControl(dc, tcRect);
else else
wxComboPopup::DefaultPaintComboControl(this,dc,rect); wxComboPopup::DefaultPaintComboControl(this, dc, tcRect);
} }
delete dcPtr;
} }
void wxGenericComboCtrl::OnMouseEvent( wxMouseEvent& event ) void wxGenericComboCtrl::OnMouseEvent( wxMouseEvent& event )