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
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;

View File

@@ -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();

View File

@@ -1071,10 +1071,10 @@ 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__
// 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
@@ -1083,17 +1083,19 @@ void wxComboCtrlBase::OnThemeChange()
vattrs.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
#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__
}
@@ -1477,15 +1479,21 @@ bool wxComboCtrlBase::SetForegroundColour(const wxColour& colour)
}
bool wxComboCtrlBase::SetBackgroundColour(const wxColour& colour)
{
if ( wxControl::SetBackgroundColour(colour) )
{
if ( m_text )
m_text->SetBackgroundColour(colour);
m_tcBgCol = colour;
m_hasBgCol = true;
return true;
}
return false;
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;

View File

@@ -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
// 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);
//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 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 )