From 40b26d752de12e3e9f03172049c441de1a5e0276 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?W=C5=82odzimierz=20Skiba?= Date: Wed, 14 Jun 2006 18:38:47 +0000 Subject: [PATCH] [ 1492053 ] Add wxVListBox style callbacks to wxOwnerDrawnComboBox. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@39730 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/combo.h | 4 +- include/wx/msw/combo.h | 2 +- include/wx/odcombo.h | 63 +++++++++++++++------- samples/combo/combo.cpp | 91 +++++--------------------------- src/common/combocmn.cpp | 2 +- src/generic/odcombo.cpp | 114 +++++++++++++++++++++++++++++++--------- src/msw/combo.cpp | 5 +- 7 files changed, 151 insertions(+), 130 deletions(-) diff --git a/include/wx/combo.h b/include/wx/combo.h index 8c15a099c6..20ef7cb5b9 100644 --- a/include/wx/combo.h +++ b/include/wx/combo.h @@ -2,7 +2,7 @@ // Name: wx/combo.h // Purpose: wxComboCtrl declaration // Author: Jaakko Salli -// Modified by: +// Modified by: // Created: Apr-30-2006 // RCS-ID: $Id$ // Copyright: (c) Jaakko Salli @@ -304,7 +304,7 @@ public: // flags: wxRendererNative flags: wxCONTROL_ISSUBMENU: is drawing a list item instead of combo control // wxCONTROL_SELECTED: list item is selected // wxCONTROL_DISABLED: control/item is disabled - virtual void DrawFocusBackground( wxDC& dc, const wxRect& rect, int flags ); + virtual void DrawFocusBackground( wxDC& dc, const wxRect& rect, int flags ) const; // Returns true if focus indicator should be drawn in the control. bool ShouldDrawFocus() const diff --git a/include/wx/msw/combo.h b/include/wx/msw/combo.h index 8478f8cff2..7204e649d8 100644 --- a/include/wx/msw/combo.h +++ b/include/wx/msw/combo.h @@ -59,7 +59,7 @@ public: virtual ~wxComboCtrl(); - virtual void DrawFocusBackground( wxDC& dc, const wxRect& rect, int flags ); + virtual void DrawFocusBackground( wxDC& dc, const wxRect& rect, int flags ) const; static int GetFeatures() { return wxComboCtrlFeatures::All; } diff --git a/include/wx/odcombo.h b/include/wx/odcombo.h index 1e3f8aaa8c..bb67677acf 100644 --- a/include/wx/odcombo.h +++ b/include/wx/odcombo.h @@ -37,13 +37,13 @@ enum // -// Callback flags +// Callback flags (see wxOwnerDrawnComboBox::OnDrawItem) // enum { // when set, we are painting the selected item in control, // not in the popup - wxCP_PAINTING_CONTROL = 0x0001 + wxODCB_PAINTING_CONTROL = 0x0001 }; @@ -84,17 +84,6 @@ public: virtual void OnComboDoubleClick(); virtual bool LazyCreate(); - // Callbacks for drawing and measuring items. Override in a derived class for - // owner-drawnness. - // item: item index to be drawn, may be wxNOT_FOUND when painting combo control itself - // and there is no valid selection - // flags: wxCP_PAINTING_CONTROL is set if painting to combo control instead of list - virtual void OnDrawItem( wxDC& dc, const wxRect& rect, int item, int flags ) const; - - // Return item width, or -1 for calculating from text extent (default) - virtual wxCoord OnMeasureItemWidth( size_t item ) const; - - // Item management void SetSelection( int item ); void Insert( const wxString& item, int pos ); @@ -132,14 +121,31 @@ protected: // Re-calculates width for given item void CheckWidth( int pos ); - // wxVListBox implementation - virtual void OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const; - //virtual wxCoord OnMeasureItem(size_t n) const; - void OnDrawBackground(wxDC& dc, const wxRect& rect, size_t n) const; + // Callbacks for drawing and measuring items. Override in a derived class for + // owner-drawnness. Font, background and text colour have been prepared according + // to selection, focus and such. + // + // item: item index to be drawn, may be wxNOT_FOUND when painting combo control itself + // and there is no valid selection + // flags: wxODCB_PAINTING_CONTROL is set if painting to combo control instead of list + // NOTE: If wxVListBoxComboPopup is used with wxComboCtrl class not derived from + // wxOwnerDrawnComboBox, this method must be overridden. + virtual void OnDrawItem( wxDC& dc, const wxRect& rect, int item, int flags ) const; - // Return item height + // This is same as in wxVListBox virtual wxCoord OnMeasureItem( size_t item ) const; + // Return item width, or -1 for calculating from text extent (default) + virtual wxCoord OnMeasureItemWidth( size_t item ) const; + + // Draw item and combo control background. Flags are same as with OnDrawItem. + // NB: Can't use name OnDrawBackground because of virtual function hiding warnings. + virtual void OnDrawBg(wxDC& dc, const wxRect& rect, int item, int flags) const; + + // Additional wxVListBox implementation (no need to override in derived classes) + virtual void OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const; + void OnDrawBackground(wxDC& dc, const wxRect& rect, size_t n) const; + // filter mouse move events happening outside the list box // move selection with cursor void OnMouseMove(wxMouseEvent& event); @@ -181,8 +187,8 @@ private: class WXDLLIMPEXP_ADV wxOwnerDrawnComboBox : public wxComboCtrl, public wxItemContainer { - friend class wxComboPopupWindow; - friend class wxComboCtrlBase; + //friend class wxComboPopupWindow; + friend class wxVListBoxComboPopup; public: // ctors and such @@ -273,6 +279,23 @@ public: protected: + // Callback for drawing. Font, background and text colour have been + // prepared according to selection, focus and such. + // item: item index to be drawn, may be wxNOT_FOUND when painting combo control itself + // and there is no valid selection + // flags: wxODCB_PAINTING_CONTROL is set if painting to combo control instead of list + virtual void OnDrawItem( wxDC& dc, const wxRect& rect, int item, int flags ) const; + + // Callback for item height, or -1 for default + virtual wxCoord OnMeasureItem( size_t item ) const; + + // Callback for item width, or -1 for default/undetermined + virtual wxCoord OnMeasureItemWidth( size_t item ) const; + + // Callback for background drawing. Flags are same as with + // OnDrawItem. + virtual void OnDrawBackground( wxDC& dc, const wxRect& rect, int item, int flags ) const; + // clears all allocated client datas void ClearClientDatas(); diff --git a/samples/combo/combo.cpp b/samples/combo/combo.cpp index 43e95ff633..3c7934c75b 100644 --- a/samples/combo/combo.cpp +++ b/samples/combo/combo.cpp @@ -396,79 +396,14 @@ END_EVENT_TABLE() // ---------------------------------------------------------------------------- // wxOwnerDrawnComboBox with custom paint list items // ---------------------------------------------------------------------------- -/* + class wxPenStyleComboBox : public wxOwnerDrawnComboBox { public: - virtual bool OnDrawListItem( wxDC& dc, const wxRect& rect, int item, int flags ) - { - wxRect r(rect); - r.Deflate(3); - r.height -= 2; - - int pen_style = wxSOLID; - if ( item == 1 ) - pen_style = wxTRANSPARENT; - else if ( item == 2 ) - pen_style = wxDOT; - else if ( item == 3 ) - pen_style = wxLONG_DASH; - else if ( item == 4 ) - pen_style = wxSHORT_DASH; - else if ( item == 5 ) - pen_style = wxDOT_DASH; - else if ( item == 6 ) - pen_style = wxBDIAGONAL_HATCH; - else if ( item == 7 ) - pen_style = wxCROSSDIAG_HATCH; - else if ( item == 8 ) - pen_style = wxFDIAGONAL_HATCH; - else if ( item == 9 ) - pen_style = wxCROSS_HATCH; - else if ( item == 10 ) - pen_style = wxHORIZONTAL_HATCH; - else if ( item == 11 ) - pen_style = wxVERTICAL_HATCH; - - wxPen pen( dc.GetTextForeground(), 3, pen_style ); - - // Get text colour as pen colour - dc.SetPen ( pen ); - - if ( !(flags & wxCP_PAINTING_CONTROL) ) - { - dc.DrawText(GetString( item ), - r.x + 3, - (r.y + 0) + ( (r.height/2) - dc.GetCharHeight() )/2 - ); - - dc.DrawLine( r.x+5, r.y+((r.height/4)*3), r.x+r.width - 5, r.y+((r.height/4)*3) ); - } - else - { - dc.DrawLine( r.x+5, r.y+r.height/2, r.x+r.width - 5, r.y+r.height/2 ); - } - - return true; - } - - virtual wxCoord OnMeasureListItem( int WXUNUSED(item) ) - { - return 24; - } - - virtual wxCoord OnMeasureListItemWidth( int WXUNUSED(item) ) - { - return -1; // default - will be measured from text width - } - -}; -*/ - -class wxPenStylePopup : public wxVListBoxComboPopup -{ -public: - virtual void OnDrawItem( wxDC& dc, const wxRect& rect, int item, int flags ) const + virtual void OnDrawItem( wxDC& dc, + const wxRect& rect, + int item, + int flags ) const { if ( item == wxNOT_FOUND ) return; @@ -506,7 +441,7 @@ public: // Get text colour as pen colour dc.SetPen ( pen ); - if ( !(flags & wxCP_PAINTING_CONTROL) ) + if ( !(flags & wxODCB_PAINTING_CONTROL) ) { dc.DrawText(GetString( item ), r.x + 3, @@ -824,15 +759,13 @@ MyFrame::MyFrame(const wxString& title) // When defining derivative class for callbacks, we need // to use two-stage creation (or redefine the common wx // constructor). - odc = new wxOwnerDrawnComboBox(panel,wxID_ANY,wxEmptyString, - wxDefaultPosition, wxDefaultSize, - arrItems, - wxCB_READONLY //wxNO_BORDER | wxCB_READONLY - ); + odc = new wxPenStyleComboBox(); + odc->Create(panel,wxID_ANY,wxEmptyString, + wxDefaultPosition, wxDefaultSize, + arrItems, + wxCB_READONLY //wxNO_BORDER | wxCB_READONLY + ); - odc->SetPopupControl( new wxPenStylePopup() ); - - //m_odc->SetCustomPaintWidth( 60 ); odc->SetSelection(0); odc->SetButtonPosition(-2, // width adjustment -6, // height adjustment diff --git a/src/common/combocmn.cpp b/src/common/combocmn.cpp index 36a3bbe91a..a1630119fb 100644 --- a/src/common/combocmn.cpp +++ b/src/common/combocmn.cpp @@ -1092,7 +1092,7 @@ void wxComboCtrlBase::DoSetToolTip(wxToolTip *tooltip) // ---------------------------------------------------------------------------- // draw focus background on area in a way typical on platform -void wxComboCtrlBase::DrawFocusBackground( wxDC& dc, const wxRect& rect, int flags ) +void wxComboCtrlBase::DrawFocusBackground( wxDC& dc, const wxRect& rect, int flags ) const { wxSize sz = GetClientSize(); bool isEnabled; diff --git a/src/generic/odcombo.cpp b/src/generic/odcombo.cpp index f19b8309d0..a568dd5784 100644 --- a/src/generic/odcombo.cpp +++ b/src/generic/odcombo.cpp @@ -103,10 +103,10 @@ void wxVListBoxComboPopup::PaintComboControl( wxDC& dc, const wxRect& rect ) { if ( !(m_combo->GetWindowStyle() & wxODCB_STD_CONTROL_PAINT) ) { - m_combo->DrawFocusBackground(dc,rect,0); + OnDrawBg(dc,rect,m_value,wxODCB_PAINTING_CONTROL); if ( m_value >= 0 ) { - OnDrawItem(dc,rect,m_value,wxCP_PAINTING_CONTROL); + OnDrawItem(dc,rect,m_value,wxODCB_PAINTING_CONTROL); return; } } @@ -128,40 +128,56 @@ void wxVListBoxComboPopup::OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) co OnDrawItem(dc,rect,(int)n,0); } -wxCoord wxVListBoxComboPopup::OnMeasureItem(size_t WXUNUSED(n)) const +wxCoord wxVListBoxComboPopup::OnMeasureItem(size_t n) const { - return m_itemHeight; + wxOwnerDrawnComboBox* combo = (wxOwnerDrawnComboBox*) m_combo; + + wxASSERT_MSG( combo->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)), + wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") ); + + wxCoord h = combo->OnMeasureItem(n); + if ( h < 0 ) + h = m_itemHeight; + return h; } -wxCoord wxVListBoxComboPopup::OnMeasureItemWidth(size_t WXUNUSED(n)) const +wxCoord wxVListBoxComboPopup::OnMeasureItemWidth(size_t n) const { - //return OnMeasureListItemWidth(n); - return -1; + wxOwnerDrawnComboBox* combo = (wxOwnerDrawnComboBox*) m_combo; + + wxASSERT_MSG( combo->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)), + wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") ); + + return combo->OnMeasureItemWidth(n); +} + +void wxVListBoxComboPopup::OnDrawBg( wxDC& dc, + const wxRect& rect, + int item, + int flags ) const +{ + wxOwnerDrawnComboBox* combo = (wxOwnerDrawnComboBox*) m_combo; + + wxASSERT_MSG( combo->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)), + wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") ); + + combo->OnDrawBackground(dc,rect,item,flags); } void wxVListBoxComboPopup::OnDrawBackground(wxDC& dc, const wxRect& rect, size_t n) const { - // we need to render selected and current items differently - if ( IsCurrent(n) ) - { - m_combo->DrawFocusBackground( dc, rect, wxCONTROL_ISSUBMENU|wxCONTROL_SELECTED ); - } - //else: do nothing for the normal items + OnDrawBg(dc,rect,(int)n,0); } // This is called from wxVListBoxComboPopup::OnDrawItem, with text colour and font prepared void wxVListBoxComboPopup::OnDrawItem( wxDC& dc, const wxRect& rect, int item, int flags ) const { - if ( flags & wxCP_PAINTING_CONTROL ) - { - dc.DrawText( m_combo->GetValue(), - rect.x + m_combo->GetTextIndent(), - (rect.height-dc.GetCharHeight())/2 + rect.y ); - } - else - { - dc.DrawText( GetString(item), rect.x + 2, rect.y ); - } + wxOwnerDrawnComboBox* combo = (wxOwnerDrawnComboBox*) m_combo; + + wxASSERT_MSG( combo->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)), + wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") ); + + combo->OnDrawItem(dc,rect,item,flags); } void wxVListBoxComboPopup::DismissWithEvent() @@ -550,7 +566,7 @@ void wxVListBoxComboPopup::Populate( const wxArrayString& choices ) // Find initial selection wxString strValue = m_combo->GetValue(); - if ( strValue.Length() ) + if ( strValue.length() ) m_value = m_strings.Index(strValue); } @@ -718,9 +734,10 @@ int wxOwnerDrawnComboBox::FindString(const wxString& s, bool bCase) const void wxOwnerDrawnComboBox::Select(int n) { - wxCHECK_RET( (n == wxNOT_FOUND) || IsValid(n), _T("invalid index in wxOwnerDrawnComboBox::Select") ); EnsurePopupControl(); + wxCHECK_RET( (n == wxNOT_FOUND) || IsValid(n), _T("invalid index in wxOwnerDrawnComboBox::Select") ); + m_popupInterface->SetSelection(n); wxString str; @@ -751,10 +768,11 @@ int wxOwnerDrawnComboBox::DoAppend(const wxString& item) int wxOwnerDrawnComboBox::DoInsert(const wxString& item, unsigned int pos) { + EnsurePopupControl(); + wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT), -1, wxT("can't insert into sorted list")); wxCHECK_MSG(IsValidInsert(pos), -1, wxT("invalid index")); - EnsurePopupControl(); m_popupInterface->Insert(item,pos); return pos; @@ -782,4 +800,48 @@ wxClientData* wxOwnerDrawnComboBox::DoGetItemClientObject(unsigned int n) const return (wxClientData*) DoGetItemClientData(n); } +// ---------------------------------------------------------------------------- +// wxOwnerDrawnComboBox item drawing and measuring default implementations +// ---------------------------------------------------------------------------- + +void wxOwnerDrawnComboBox::OnDrawItem( wxDC& dc, + const wxRect& rect, + int item, + int flags ) const +{ + if ( flags & wxODCB_PAINTING_CONTROL ) + { + dc.DrawText( GetValue(), + rect.x + GetTextIndent(), + (rect.height-dc.GetCharHeight())/2 + rect.y ); + } + else + { + dc.DrawText( m_popupInterface->GetString(item), rect.x + 2, rect.y ); + } +} + +wxCoord wxOwnerDrawnComboBox::OnMeasureItem( size_t WXUNUSED(item) ) const +{ + return -1; +} + +wxCoord wxOwnerDrawnComboBox::OnMeasureItemWidth( size_t WXUNUSED(item) ) const +{ + return -1; +} + +void wxOwnerDrawnComboBox::OnDrawBackground(wxDC& dc, const wxRect& rect, int item, int flags) const +{ + // we need to render selected and current items differently + if ( m_popupInterface->IsCurrent((size_t)item) ) + { + DrawFocusBackground(dc, + rect, + (flags&wxODCB_PAINTING_CONTROL?0:wxCONTROL_ISSUBMENU) | + wxCONTROL_SELECTED); + } + //else: do nothing for the normal items +} + #endif // wxUSE_ODCOMBOBOX diff --git a/src/msw/combo.cpp b/src/msw/combo.cpp index 7ebac8b6aa..c51a4bc77e 100644 --- a/src/msw/combo.cpp +++ b/src/msw/combo.cpp @@ -239,9 +239,12 @@ static void wxMSWDrawFocusRect( wxDC& dc, const wxRect& rect ) } // draw focus background on area in a way typical on platform -void wxComboCtrl::DrawFocusBackground( wxDC& dc, const wxRect& rect, int flags ) +void wxComboCtrl::DrawFocusBackground( wxDC& dc, const wxRect& rect, int flags ) const { wxUxThemeEngine* theme = (wxUxThemeEngine*) NULL; + + // Constructor only calls GetHWND() const, so it should be safe + // to cast "this" to const. wxUxThemeHandle hTheme(this, L"COMBOBOX"); //COLORREF cref;