From: Vadim Zeitlin Date: Tue, 9 May 2006 16:18:19 +0000 (+0000) Subject: fixes and missing files from the first wxComboControl patch (update of patch 1479938) X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/6d0ce565ff6a0db2e7c6e3240ef4cf6fe7950a35 fixes and missing files from the first wxComboControl patch (update of patch 1479938) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@39126 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/combo.h b/include/wx/combo.h index 4de9e3a714..a1ef01b268 100644 --- a/include/wx/combo.h +++ b/include/wx/combo.h @@ -157,17 +157,15 @@ public: bool IsPopupShown() const { return m_isPopupShown; } // set interface class instance derived from wxComboPopup - void SetPopupControl( wxComboPopup* iface ); + // NULL popup can be used to indicate default in a derived class + virtual void SetPopupControl( wxComboPopup* popup ); // get interface class instance derived from wxComboPopup - wxComboPopup* GetPopup() const { return m_popupInterface; } + wxComboPopup* GetPopupControl() const { return m_popupInterface; } // get the popup window containing the popup control wxWindow *GetPopupWindow() const { return m_winPopup; } - // get the popup control/panel in window - wxWindow *GetPopupControl() const { return m_popup; } - // Get the text control which is part of the combobox. wxTextCtrl *GetTextCtrl() const { return m_text; } @@ -199,6 +197,10 @@ public: virtual void SetSelection(long from, long to); virtual void Undo(); + // This method sets the text without affecting list selection + // (ie. wxComboPopup::SetStringValue doesn't get called). + void SetText(const wxString& value); + // // Popup customization methods // @@ -254,23 +256,25 @@ public: // spacingX: empty space on sides of the button. Default is 0. // Remarks: // There is no spacingY - the button will be centered vertically. - void SetButtonPosition( int width = 0, int height = 0, int side = wxRIGHT, - int spacingX = 0 /*, int spacingY = 0*/ ); + void SetButtonPosition( int width = 0, + int height = 0, + int side = wxRIGHT, + int spacingX = 0 ); // // Sets dropbutton to be drawn with custom bitmaps. // // bmpNormal: drawn when cursor is not on button - // blankButtonBg: Draw blank button background below the image. - // NOTE! This is only properly supported on platforms with appropriate - // method in wxRendererNative. + // pushButtonBg: Draw push button background below the image. + // NOTE! This is usually only properly supported on platforms with appropriate + // method in wxRendererNative. // bmpPressed: drawn when button is depressed // bmpHover: drawn when cursor hovers on button. This is ignored on platforms // that do not generally display hover differently. // bmpDisabled: drawn when combobox is disabled. void SetButtonBitmaps( const wxBitmap& bmpNormal, - bool blankButtonBg = false, + bool pushButtonBg = false, const wxBitmap& bmpPressed = wxNullBitmap, const wxBitmap& bmpHover = wxNullBitmap, const wxBitmap& bmpDisabled = wxNullBitmap ); @@ -303,7 +307,7 @@ public: // wxCONTROL_DISABLED: control/item is disabled virtual void DrawFocusBackground( wxDC& dc, const wxRect& rect, int flags ); - // Returns true if focus indicator should be drawn. + // Returns true if focus indicator should be drawn in the control. bool ShouldDrawFocus() const { const wxWindow* curFocus = FindFocus(); @@ -324,25 +328,6 @@ public: // Return true if Create has finished bool IsCreated() const { return m_iFlags & wxCC_IFLAG_CREATED ? true : false; } - // Popup may use these as callbacks to measure and draw list items. - // (wxOwnerDrawnComboBox uses these, obviously) - // item: -1 means item is the combo control itself - // flags: wxCC_PAINTING_CONTROL is set if painting to combo control instead of list - // return value: OnDrawListItem must return true if it did anything - virtual bool OnDrawListItem( wxDC& dc, const wxRect& rect, int item, int flags ); - - // Return item height, or -1 for text height (default) - virtual wxCoord OnMeasureListItem( int item ); - - // Return item width, or -1 for calculating from text extent (default) - virtual wxCoord OnMeasureListItemWidth( int item ); - - // NOTE: - // I basicly needed to add callback methods into wxComboControlBase - otherwise it - // will not be easily possible to use wxVListBoxComboPopup from simultaneously existing - // wxComboControl and wxGenericComboControl (since some native implementations - // might not have all the features, I really would like to have this options). - // common code to be called on popup hide/dismiss void OnPopupDismiss(); @@ -395,6 +380,9 @@ protected: virtual void DoMoveWindow(int x, int y, int width, int height); virtual wxSize DoGetBestSize() const; + // ensures there is atleast the default popup + void EnsurePopupControl(); + // Recalculates button and textctrl areas. Called when size or button setup change. // btnWidth: default/calculated width of the dropbutton. 0 means unchanged, // just recalculate. @@ -433,7 +421,7 @@ protected: wxWindow* m_popup; // popup interface - wxComboPopup* m_popupInterface; + wxComboPopup* m_popupInterface; // this is for this control itself wxEvtHandler* m_extraEvtHandler; @@ -534,8 +522,7 @@ private: // wxComboPopup internal flags enum { - // Set by wxComboControlBase after Create is called - wxCP_IFLAG_CREATED = 0x0001 + wxCP_IFLAG_CREATED = 0x0001 // Set by wxComboControlBase after Create is called }; @@ -543,12 +530,18 @@ class WXDLLEXPORT wxComboPopup { friend class wxComboControlBase; public: - wxComboPopup(wxComboControlBase *combo) + wxComboPopup() { - m_combo = combo; + m_combo = (wxComboControlBase*) NULL; m_iFlags = 0; } + // This is called immediately after construction finishes. m_combo member + // variable has been initialized before the call. + // NOTE: It is not in constructor so the derived class doesn't need to redefine + // a default constructor of its own. + virtual void Init() { }; + virtual ~wxComboPopup(); // Create the popup child control. @@ -609,9 +602,21 @@ public: return (m_iFlags & wxCP_IFLAG_CREATED) ? true : false; } + // Default PaintComboControl behaviour + static void DefaultPaintComboControl( wxComboControlBase* combo, + wxDC& dc, + const wxRect& rect ); + protected: wxComboControlBase* m_combo; wxUint32 m_iFlags; + +private: + // Called in wxComboControlBase::SetPopupControl + void InitBase(wxComboControlBase *combo) + { + m_combo = combo; + } }; diff --git a/include/wx/odcombo.h b/include/wx/odcombo.h index 33d7025e55..b5f65833d3 100644 --- a/include/wx/odcombo.h +++ b/include/wx/odcombo.h @@ -43,7 +43,7 @@ enum { // when set, we are painting the selected item in control, // not in the popup - wxCC_PAINTING_CONTROL = 0x0001 + wxCP_PAINTING_CONTROL = 0x0001 }; @@ -64,11 +64,12 @@ class WXDLLEXPORT wxVListBoxComboPopup : public wxVListBox, public wxComboPopup friend class wxOwnerDrawnComboBox; public: - // ctor and dtor - wxVListBoxComboPopup(wxComboControlBase* combo); + // init and dtor + wxVListBoxComboPopup() : wxVListBox(), wxComboPopup() { } virtual ~wxVListBoxComboPopup(); // required virtuals + virtual void Init(); virtual bool Create(wxWindow* parent); virtual wxWindow *GetControl() { return this; } virtual void SetStringValue( const wxString& value ); @@ -82,6 +83,20 @@ 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 height + 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; + + // Item management void SetSelection( int item ); void Insert( const wxString& item, int pos ); @@ -94,8 +109,10 @@ public: wxString GetString( int item ) const; unsigned int GetCount() const; int FindString(const wxString& s) const; + int GetSelection() const; - void Populate( int n, const wxString choices[] ); + //void Populate( int n, const wxString choices[] ); + void Populate( const wxArrayString& choices ); void ClearClientDatas(); // helpers @@ -109,14 +126,17 @@ protected: bool HandleKey( int keycode, bool saturate ); // sends combobox select event from the parent combo control - void SendComboBoxEvent(); + void SendComboBoxEvent( int selection ); + + // gets value, sends event and dismisses + void DismissWithEvent(); // 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; + //virtual wxCoord OnMeasureItem(size_t n) const; void OnDrawBackground(wxDC& dc, const wxRect& rect, size_t n) const; // filter mouse move events happening outside the list box @@ -130,8 +150,9 @@ protected: wxArrayPtrVoid m_clientDatas; wxArrayInt m_widths; // cached line widths - wxFont m_font; + wxFont m_useFont; + //wxString m_stringValue; // displayed text (may be different than m_strings[m_value]) int m_value; // selection int m_itemHover; // on which item the cursor is int m_widestWidth; // width of widest item thus far @@ -225,6 +246,9 @@ public: virtual ~wxOwnerDrawnComboBox(); + // NULL popup can be used to indicate default interface + virtual void SetPopupControl( wxComboPopup* popup ); + // wxControlWithItems methods virtual void Clear(); virtual void Delete(unsigned int n); @@ -253,6 +277,11 @@ protected: // overload m_popupInterface member so we can access specific popup interface easier wxVListBoxComboPopup* m_popupInterface; + // temporary storage for the initial choices + //const wxString* m_baseChoices; + //int m_baseChoicesCount; + wxArrayString m_initChs; + private: void Init(); diff --git a/include/wx/univ/combobox.h b/include/wx/univ/combobox.h index 8c9eb4fcdc..f76985d6a6 100644 --- a/include/wx/univ/combobox.h +++ b/include/wx/univ/combobox.h @@ -9,198 +9,23 @@ // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// -/* - A few words about all the classes defined in this file are probably in - order: why do we need extra wxComboControl and wxComboPopup classes? - - This is because a traditional combobox is a combination of a text control - (with a button allowing to open the pop down list) with a listbox and - wxComboBox class is exactly such control, however we want to also have other - combinations - in fact, we want to allow anything at all to be used as pop - down list, not just a wxListBox. - - So we define a base wxComboControl which can use any control as pop down - list and wxComboBox deriving from it which implements the standard wxWidgets - combobox API. wxComboControl needs to be told somehow which control to use - and this is done by SetPopupControl(). However, we need something more than - just a wxControl in this method as, for example, we need to call - SetSelection("initial text value") and wxControl doesn't have such method. - So we also need a wxComboPopup which is just a very simple interface which - must be implemented by a control to be usable as a popup. - - We couldn't derive wxComboPopup from wxControl as this would make it - impossible to have a class deriving from both wxListBx and from it, so - instead it is just a mix-in. - */ #ifndef _WX_UNIV_COMBOBOX_H_ #define _WX_UNIV_COMBOBOX_H_ -class WXDLLEXPORT wxComboControl; +#include "wx/combo.h" + class WXDLLEXPORT wxListBox; -class WXDLLEXPORT wxPopupComboWindow; -class WXDLLEXPORT wxTextCtrl; -class WXDLLEXPORT wxButton; // ---------------------------------------------------------------------------- -// the actions supported by this control +// NB: some actions supported by this control are in wx/generic/combo.h // ---------------------------------------------------------------------------- -// all actions of single line text controls are supported - -// popup/dismiss the choice window -#define wxACTION_COMBOBOX_POPUP _T("popup") -#define wxACTION_COMBOBOX_DISMISS _T("dismiss") - // choose the next/prev/specified (by numArg) item #define wxACTION_COMBOBOX_SELECT_NEXT _T("next") #define wxACTION_COMBOBOX_SELECT_PREV _T("prev") #define wxACTION_COMBOBOX_SELECT _T("select") -// ---------------------------------------------------------------------------- -// wxComboPopup is the interface which must be implemented by a control to be -// used as a popup by wxComboControl -// ---------------------------------------------------------------------------- - -class WXDLLEXPORT wxComboPopup -{ -public: - wxComboPopup(wxComboControl *combo) { m_combo = combo; } - virtual ~wxComboPopup() {} - - // we must have an associated control which is subclassed by the combobox - virtual wxControl *GetControl() = 0; - - // called before showing the control to set the initial selection - notice - // that the text passed to this method might not correspond to any valid - // item (if the user edited it directly), in which case the method should - // just return false but not emit any errors - virtual bool SetSelection(const wxString& value) = 0; - - // called immediately after the control is shown - virtual void OnShow() = 0; - - virtual wxCoord GetBestWidth() const {return 0; } - -protected: - wxComboControl *m_combo; -}; - -// ---------------------------------------------------------------------------- -// wxComboControl: a combination of a (single line) text control with a button -// opening a popup window which contains the control from which the user can -// choose the value directly. -// ---------------------------------------------------------------------------- - -class WXDLLEXPORT wxComboControl : public wxControl -{ -public: - // construction - wxComboControl() - { - Init(); - } - - wxComboControl(wxWindow *parent, - wxWindowID id, - const wxString& value = wxEmptyString, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = 0, - const wxValidator& validator = wxDefaultValidator, - const wxString& name = wxComboBoxNameStr) - { - Init(); - - (void)Create(parent, id, value, pos, size, style, validator, name); - } - - bool Create(wxWindow *parent, - wxWindowID id, - const wxString& value = wxEmptyString, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = 0, - const wxValidator& validator = wxDefaultValidator, - const wxString& name = wxComboBoxNameStr); - - virtual ~wxComboControl(); - - // a combo control needs a control for popup window it displays - void SetPopupControl(wxComboPopup *popup); - wxComboPopup *GetPopupControl() const { return m_popup; } - - // show/hide popup window - void ShowPopup(); - void HidePopup(); - - // return true if the popup is currently shown - bool IsPopupShown() const { return m_isPopupShown; } - - // get the popup window containing the popup control - wxPopupComboWindow *GetPopupWindow() const { return m_winPopup; } - - // get the text control which is part of the combobox - wxTextCtrl *GetText() const { return m_text; } - - // implementation only from now on - // ------------------------------- - - // notifications from wxComboPopup (shouldn't be called by anybody else) - - // called when the user selects something in the popup: this normally hides - // the popup and sets the text to the new value - virtual void OnSelect(const wxString& value); - - // called when the user dismisses the popup - virtual void OnDismiss(); - - // forward these functions to all subcontrols - virtual bool Enable(bool enable = true); - virtual bool Show(bool show = true); - -#if wxUSE_TOOLTIPS - virtual void DoSetToolTip( wxToolTip *tip ); -#endif // wxUSE_TOOLTIPS - - // we have our own input handler and our own actions - virtual bool PerformAction(const wxControlAction& action, - long numArg = 0l, - const wxString& strArg = wxEmptyString); - -protected: - // override the base class virtuals involved into geometry calculations - virtual wxSize DoGetBestClientSize() const; - virtual void DoMoveWindow(int x, int y, int width, int height); - virtual void DoSetSize(int x, int y, - int width, int height, - int sizeFlags = wxSIZE_AUTO); - - // event handlers - void OnKey(wxKeyEvent& event); - - // common part of all ctors - void Init(); - -private: - // the text control and button we show all the time - wxTextCtrl *m_text; - wxButton *m_btn; - - // the popup control - wxComboPopup *m_popup; - - // and the popup window containing it - wxPopupComboWindow *m_winPopup; - - // the height of the combobox popup as calculated in Create() - wxCoord m_heightPopup; - - // is the popup window currenty shown? - bool m_isPopupShown; - - DECLARE_EVENT_TABLE() -}; // ---------------------------------------------------------------------------- // wxComboBox: a combination of text control and a listbox @@ -303,6 +128,14 @@ public: wxCONTROL_ITEMCONTAINER_CLIENTDATAOBJECT_RECAST + // we have our own input handler and our own actions + // (but wxComboControl already handled Popup/Dismiss) + /* + virtual bool PerformAction(const wxControlAction& action, + long numArg = 0l, + const wxString& strArg = wxEmptyString); + */ + protected: virtual int DoAppend(const wxString& item); virtual int DoInsert(const wxString& item, unsigned int pos); @@ -325,6 +158,7 @@ private: DECLARE_DYNAMIC_CLASS(wxComboBox) }; + // ---------------------------------------------------------------------------- // wxStdComboBoxInputHandler: allows the user to open/close the combo from kbd // ---------------------------------------------------------------------------- @@ -339,4 +173,5 @@ public: bool pressed); }; + #endif // _WX_UNIV_COMBOBOX_H_ diff --git a/samples/combo/combo.cpp b/samples/combo/combo.cpp index 7d96e34276..89b115bdaf 100644 --- a/samples/combo/combo.cpp +++ b/samples/combo/combo.cpp @@ -163,12 +163,19 @@ class ListViewComboPopup : public wxListView, public wxComboPopup { public: +/* ListViewComboPopup(wxComboControlBase* combo) : wxListView(), wxComboPopup(combo) { m_value = -1; m_itemHere = -1; // hot item in list } +*/ + virtual void Init() + { + m_value = -1; + m_itemHere = -1; // hot item in list + } virtual bool Create( wxWindow* parent ) { @@ -258,10 +265,16 @@ class TreeCtrlComboPopup : public wxTreeCtrl, public wxComboPopup { public: +/* TreeCtrlComboPopup(wxComboControlBase* combo) : wxTreeCtrl(), wxComboPopup(combo) { } +*/ + + virtual void Init() + { + } virtual bool Create( wxWindow* parent ) { @@ -383,7 +396,7 @@ END_EVENT_TABLE() // ---------------------------------------------------------------------------- // wxOwnerDrawnComboBox with custom paint list items // ---------------------------------------------------------------------------- - +/* class wxPenStyleComboBox : public wxOwnerDrawnComboBox { public: @@ -422,7 +435,7 @@ public: // Get text colour as pen colour dc.SetPen ( pen ); - if ( !(flags & wxCC_PAINTING_CONTROL) ) + if ( !(flags & wxCP_PAINTING_CONTROL) ) { dc.DrawText(GetString( item ), r.x + 3, @@ -430,31 +443,90 @@ public: ); 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 + } - /* - dc.SetBrush( *wxTRANSPARENT_BRUSH ); - dc.DrawRectangle( r ); +}; +*/ + +class wxPenStylePopup : public wxVListBoxComboPopup +{ +public: + virtual void OnDrawItem( wxDC& dc, const wxRect& rect, int item, int flags ) const + { + if ( item == wxNOT_FOUND ) + return; + 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) - dc.GetCharHeight() )/2 + (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) ) + virtual wxCoord OnMeasureItem( size_t WXUNUSED(item) ) const { return 24; } - virtual wxCoord OnMeasureListItemWidth( int WXUNUSED(item) ) + virtual wxCoord OnMeasureItemWidth( size_t WXUNUSED(item) ) const { return -1; // default - will be measured from text width } @@ -634,10 +706,10 @@ MyFrame::MyFrame(const wxString& title) wxALIGN_CENTER_VERTICAL|wxRIGHT|wxEXPAND, border ); odc = new wxOwnerDrawnComboBox(panel,wxID_ANY,wxEmptyString, - wxDefaultPosition, wxDefaultSize, - arrItems, - wxCB_SORT // wxNO_BORDER|wxCB_READONLY - ); + wxDefaultPosition, wxDefaultSize, + arrItems, + wxCB_SORT // wxNO_BORDER|wxCB_READONLY + ); odc->Append(wxT("H - Appended Item")); // test sorting in append @@ -651,12 +723,13 @@ MyFrame::MyFrame(const wxString& title) wxALIGN_CENTER_VERTICAL|wxRIGHT, border ); odc = new wxOwnerDrawnComboBox(panel,wxID_ANY,wxEmptyString, - wxDefaultPosition, wxDefaultSize, - arrItems, - wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY - ); + wxDefaultPosition, wxDefaultSize, + arrItems, + wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY + ); odc->SetValue(wxT("Dot Dash")); + odc->SetText(wxT("Dot Dash (Testing SetText)")); groupSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border ); @@ -751,12 +824,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 wxPenStyleComboBox(); - odc->Create(panel,wxID_ANY,wxEmptyString, - wxDefaultPosition, wxDefaultSize, - arrItems, - wxCB_READONLY //wxNO_BORDER | wxCB_READONLY - ); + odc = new wxOwnerDrawnComboBox(panel,wxID_ANY,wxEmptyString, + wxDefaultPosition, wxDefaultSize, + arrItems, + wxCB_READONLY //wxNO_BORDER | wxCB_READONLY + ); + + odc->SetPopupControl( new wxPenStylePopup() ); //m_odc->SetCustomPaintWidth( 60 ); odc->SetSelection(0); @@ -788,7 +862,7 @@ MyFrame::MyFrame(const wxString& title) cc->SetPopupMinWidth(300); - ListViewComboPopup* iface = new ListViewComboPopup(cc); + ListViewComboPopup* iface = new ListViewComboPopup(); cc->SetPopupControl(iface); iface->AddSelection( wxT("Cabbage") ); @@ -823,7 +897,7 @@ MyFrame::MyFrame(const wxString& title) // Set popup interface right away, otherwise some of the calls // below may fail - TreeCtrlComboPopup* tcPopup = new TreeCtrlComboPopup(gcc); + TreeCtrlComboPopup* tcPopup = new TreeCtrlComboPopup(); gcc->SetPopupControl(tcPopup); // Add items using wxTreeCtrl methods directly diff --git a/src/common/combocmn.cpp b/src/common/combocmn.cpp index 3ae8b2c22d..9fb6a422e2 100644 --- a/src/common/combocmn.cpp +++ b/src/common/combocmn.cpp @@ -381,18 +381,24 @@ wxSize wxComboPopup::GetAdjustedSize( int minWidth, return wxSize(minWidth,prefHeight); } -void wxComboPopup::PaintComboControl( wxDC& dc, const wxRect& rect ) +void wxComboPopup::DefaultPaintComboControl( wxComboControlBase* combo, + wxDC& dc, const wxRect& rect ) { - if ( m_combo->GetWindowStyle() & wxCB_READONLY ) // ie. no textctrl + if ( combo->GetWindowStyle() & wxCB_READONLY ) // ie. no textctrl { - m_combo->DrawFocusBackground(dc,rect,0); + combo->DrawFocusBackground(dc,rect,0); - dc.DrawText( GetStringValue(), - rect.x + m_combo->GetTextIndent(), - (rect.height-dc.GetCharHeight())/2 + m_combo->m_widthCustomBorder ); + dc.DrawText( combo->GetValue(), + rect.x + combo->GetTextIndent(), + (rect.height-dc.GetCharHeight())/2 + rect.y ); } } +void wxComboPopup::PaintComboControl( wxDC& dc, const wxRect& rect ) +{ + DefaultPaintComboControl(m_combo,dc,rect); +} + void wxComboPopup::OnComboKeyEvent( wxKeyEvent& event ) { event.Skip(); @@ -469,12 +475,12 @@ void wxComboBoxExtraInputHandler::OnKey(wxKeyEvent& event) if ( m_combo->IsPopupShown() ) { // pass it to the popped up control - m_combo->GetPopupControl()->AddPendingEvent(event); + m_combo->GetPopupControl()->GetControl()->AddPendingEvent(event); } else // no popup { int comboStyle = m_combo->GetWindowStyle(); - wxComboPopup* popupInterface = m_combo->GetPopup(); + wxComboPopup* popupInterface = m_combo->GetPopupControl(); if ( !popupInterface ) { @@ -494,6 +500,8 @@ void wxComboBoxExtraInputHandler::OnKey(wxKeyEvent& event) m_combo->OnButtonClick(); return; } + else + event.Skip(); } else popupInterface->OnComboKeyEvent(event); @@ -503,7 +511,6 @@ void wxComboBoxExtraInputHandler::OnKey(wxKeyEvent& event) } } - void wxComboBoxExtraInputHandler::OnFocus(wxFocusEvent& event) { // FIXME: This code does run when control is clicked, @@ -516,6 +523,18 @@ void wxComboBoxExtraInputHandler::OnFocus(wxFocusEvent& event) m_combo->SetSelection(-1,-1); } + if ( event.GetId() != m_combo->GetId() ) + { + // Add textctrl set focus events as combo set focus events + // NOTE: Simply changing the event and skipping didn't seem + // to do the trick. + wxFocusEvent evt2(wxEVT_SET_FOCUS,m_combo->GetId()); + evt2.SetEventObject(m_combo); + m_combo->GetEventHandler()->ProcessEvent(evt2); + } + else + event.Skip(); + event.Skip(); } @@ -538,7 +557,7 @@ public: void OnMouseEvent( wxMouseEvent& event ); - // Called from wxPGComboControlBase::OnPopupDismiss + // Called from wxComboControlBase::OnPopupDismiss void OnPopupDismiss() { m_beenInside = false; @@ -547,7 +566,7 @@ public: protected: wxComboControlBase* m_combo; - bool m_beenInside; + bool m_beenInside; private: DECLARE_EVENT_TABLE() @@ -562,7 +581,7 @@ END_EVENT_TABLE() void wxComboPopupExtraEventHandler::OnMouseEvent( wxMouseEvent& event ) { wxPoint pt = event.GetPosition(); - wxSize sz = m_combo->GetPopupControl()->GetClientSize(); + wxSize sz = m_combo->GetPopupControl()->GetControl()->GetClientSize(); int evtType = event.GetEventType(); bool isInside = pt.x >= 0 && pt.y >= 0 && pt.x < sz.x && pt.y < sz.y; @@ -1238,25 +1257,6 @@ wxBitmap& wxComboControlBase::GetBufferBitmap( const wxSize& sz ) const return *gs_doubleBuffer; } - -bool wxComboControlBase::OnDrawListItem( wxDC& WXUNUSED(dc), - const wxRect& WXUNUSED(rect), - int WXUNUSED(item), - int WXUNUSED(flags) ) -{ - return false; // signals caller to make default drawing -} - -wxCoord wxComboControlBase::OnMeasureListItem( int WXUNUSED(item) ) -{ - return -1; // signals caller to use default -} - -wxCoord wxComboControlBase::OnMeasureListItemWidth( int WXUNUSED(item) ) -{ - return -1; // signals caller to use default -} - // ---------------------------------------------------------------------------- // miscellaneous event handlers // ---------------------------------------------------------------------------- @@ -1519,9 +1519,14 @@ void wxComboControlBase::CreatePopup() void wxComboControlBase::SetPopupControl( wxComboPopup* iface ) { + wxCHECK_RET( iface, wxT("no popup interface set for wxComboControl") ); + delete m_popupInterface; delete m_winPopup; + iface->InitBase(this); + iface->Init(); + m_popupInterface = iface; if ( !iface->LazyCreate() || m_winPopup ) @@ -1533,10 +1538,19 @@ void wxComboControlBase::SetPopupControl( wxComboPopup* iface ) m_popup = (wxWindow*) NULL; } - // This must be after creation - if ( m_valueString ) + // This must be done after creation + if ( m_valueString.length() ) + { iface->SetStringValue(m_valueString); + //Refresh(); + } +} +// Ensures there is atleast the default popup +void wxComboControlBase::EnsurePopupControl() +{ + if ( !m_popupInterface ) + SetPopupControl(NULL); } void wxComboControlBase::OnButtonClick() @@ -1548,7 +1562,7 @@ void wxComboControlBase::OnButtonClick() void wxComboControlBase::ShowPopup() { - wxCHECK_RET( m_popupInterface, wxT("no popup interface set for wxComboControl") ); + EnsurePopupControl(); wxCHECK_RET( !IsPopupShown(), wxT("popup window already shown") ); SetFocus(); @@ -1663,7 +1677,6 @@ void wxComboControlBase::ShowPopup() else { // This is neede since focus/selection indication may change when popup is shown - // FIXME: But in that case, would m_isPopupShown need to go before this? Refresh(); } @@ -1859,12 +1872,24 @@ void wxComboControlBase::SetValue(const wxString& value) m_text->SelectAll(); } + m_valueString = value; + + Refresh(); + // Since wxComboPopup may want to paint the combo as well, we need // to set the string value here (as well as sometimes in ShowPopup). if ( m_valueString != value && m_popupInterface ) { m_popupInterface->SetStringValue(value); } +} + +// In this SetValue variant wxComboPopup::SetStringValue is not called +void wxComboControlBase::SetText(const wxString& value) +{ + // Unlike in SetValue(), this must be called here or + // the behaviour will no be consistent in readonlys. + EnsurePopupControl(); m_valueString = value; diff --git a/src/generic/combog.cpp b/src/generic/combog.cpp index 3b62ca9bc5..edf2bba3d6 100644 --- a/src/generic/combog.cpp +++ b/src/generic/combog.cpp @@ -260,7 +260,7 @@ void wxGenericComboControl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) DrawButton(dc,rectb,true); // paint required portion on the control - if ( !m_text || m_widthCustomPaint ) + if ( (!m_text || m_widthCustomPaint) ) { wxASSERT( m_widthCustomPaint >= 0 ); @@ -272,7 +272,10 @@ void wxGenericComboControl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) dc.SetFont( GetFont() ); dc.SetClippingRegion(rect); - m_popupInterface->PaintComboControl(dc,rect); + if ( m_popupInterface ) + m_popupInterface->PaintComboControl(dc,rect); + else + wxComboPopup::DefaultPaintComboControl(this,dc,rect); } } @@ -286,7 +289,14 @@ void wxGenericComboControl::OnMouseEvent( wxMouseEvent& event ) if ( PreprocessMouseEvent(event,handlerFlags) ) return; - if ( (m_windowStyle & (wxCC_SPECIAL_DCLICK|wxCB_READONLY)) == wxCB_READONLY ) +#ifdef __WXMSW__ + const bool ctrlIsButton = true; +#else + const bool ctrlIsButton = false; +#endif + + if ( ctrlIsButton && + (m_windowStyle & (wxCC_SPECIAL_DCLICK|wxCB_READONLY)) == wxCB_READONLY ) { // if no textctrl and no special double-click, then the entire control acts // as a button diff --git a/src/generic/odcombo.cpp b/src/generic/odcombo.cpp index ee1741bea2..eb126c330f 100644 --- a/src/generic/odcombo.cpp +++ b/src/generic/odcombo.cpp @@ -55,9 +55,9 @@ BEGIN_EVENT_TABLE(wxVListBoxComboPopup, wxVListBox) END_EVENT_TABLE() -wxVListBoxComboPopup::wxVListBoxComboPopup(wxComboControlBase* combo) - : wxVListBox(), - wxComboPopup(combo) +void wxVListBoxComboPopup::Init() +/* : wxVListBox(), + wxComboPopup(combo)*/ { m_widestWidth = 0; m_avgCharWidth = 0; @@ -77,8 +77,7 @@ bool wxVListBoxComboPopup::Create(wxWindow* parent) wxBORDER_SIMPLE | wxLB_INT_HEIGHT | wxWANTS_CHARS) ) return false; - wxASSERT( GetParent()->GetParent() ); - SetFont( GetParent()->GetParent()->GetFont() ); + m_useFont = m_combo->GetFont(); wxVListBox::SetItemCount(m_strings.GetCount()); @@ -109,8 +108,8 @@ void wxVListBoxComboPopup::PaintComboControl( wxDC& dc, const wxRect& rect ) m_combo->DrawFocusBackground(dc,rect,0); if ( m_value >= 0 ) { - if ( m_combo->OnDrawListItem(dc,rect,m_value,wxCC_PAINTING_CONTROL) ) - return; + OnDrawItem(dc,rect,m_value,wxCP_PAINTING_CONTROL); + return; } } @@ -119,29 +118,32 @@ void wxVListBoxComboPopup::PaintComboControl( wxDC& dc, const wxRect& rect ) void wxVListBoxComboPopup::OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const { - dc.SetFont( m_font ); - - bool isHilited = GetSelection() == (int) n; + // TODO: Maybe this code could be moved to wxVListBox::OnPaint? + dc.SetFont(m_useFont); // Set correct text colour for selected items - // (must always set the correct colour - atleast GTK may have lost it - // in between calls). - if ( isHilited ) + if ( wxVListBox::GetSelection() == (int) n ) dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) ); else dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) ); - if ( !m_combo->OnDrawListItem(dc,rect,(int)n,0) ) - dc.DrawText( GetString(n), rect.x + 2, rect.y ); + OnDrawItem(dc,rect,(int)n,0); } -wxCoord wxVListBoxComboPopup::OnMeasureItem(size_t n) const +wxCoord wxVListBoxComboPopup::OnMeasureItem(size_t WXUNUSED(n)) const { + /* int itemHeight = m_combo->OnMeasureListItem(n); if ( itemHeight < 0 ) itemHeight = m_itemHeight; + */ + return m_itemHeight; +} - return itemHeight; +wxCoord wxVListBoxComboPopup::OnMeasureItemWidth(size_t WXUNUSED(n)) const +{ + //return OnMeasureListItemWidth(n); + return -1; } void wxVListBoxComboPopup::OnDrawBackground(wxDC& dc, const wxRect& rect, size_t n) const @@ -154,12 +156,47 @@ void wxVListBoxComboPopup::OnDrawBackground(wxDC& dc, const wxRect& rect, size_t //else: do nothing for the normal items } -void wxVListBoxComboPopup::SendComboBoxEvent() +// 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 ); + } +} + +void wxVListBoxComboPopup::DismissWithEvent() +{ + int selection = wxVListBox::GetSelection(); + + Dismiss(); + + wxString valStr; + if ( selection != wxNOT_FOUND ) + valStr = m_strings[selection]; + else + valStr = wxEmptyString; + + m_value = selection; + + if ( valStr != m_combo->GetValue() ) + m_combo->SetValue(valStr); + + SendComboBoxEvent(selection); +} + +void wxVListBoxComboPopup::SendComboBoxEvent( int selection ) { wxCommandEvent evt(wxEVT_COMMAND_COMBOBOX_SELECTED,m_combo->GetId()); - int selection = m_value; evt.SetEventObject(m_combo); + evt.SetInt(selection); // Set client data, if any @@ -232,11 +269,10 @@ bool wxVListBoxComboPopup::HandleKey( int keycode, bool saturate ) m_value = value; - wxString valStr; if ( value >= 0 ) m_combo->SetValue(m_strings[value]); - SendComboBoxEvent(); + SendComboBoxEvent(m_value); return true; } @@ -275,9 +311,7 @@ void wxVListBoxComboPopup::OnMouseMove(wxMouseEvent& event) void wxVListBoxComboPopup::OnLeftClick(wxMouseEvent& WXUNUSED(event)) { - m_value = wxVListBox::GetSelection(); - Dismiss(); - SendComboBoxEvent(); + DismissWithEvent(); } void wxVListBoxComboPopup::OnKey(wxKeyEvent& event) @@ -285,9 +319,7 @@ void wxVListBoxComboPopup::OnKey(wxKeyEvent& event) // Select item if ENTER is pressed if ( event.GetKeyCode() == WXK_RETURN || event.GetKeyCode() == WXK_NUMPAD_ENTER ) { - m_value = wxVListBox::GetSelection(); - Dismiss(); - SendComboBoxEvent(); + DismissWithEvent(); } // Hide popup if ESC is pressed else if ( event.GetKeyCode() == WXK_ESCAPE ) @@ -298,15 +330,15 @@ void wxVListBoxComboPopup::OnKey(wxKeyEvent& event) void wxVListBoxComboPopup::CheckWidth( int pos ) { - wxCoord x = m_combo->OnMeasureListItemWidth(pos); + wxCoord x = OnMeasureItemWidth(pos); if ( x < 0 ) { - if ( !m_font.Ok() ) - m_font = m_combo->GetFont(); + if ( !m_useFont.Ok() ) + m_useFont = m_combo->GetFont(); wxCoord y; - m_combo->GetTextExtent(m_strings[pos], &x, &y, 0, 0, &m_font); + m_combo->GetTextExtent(m_strings[pos], &x, &y, 0, 0, &m_useFont); x += 4; } @@ -322,7 +354,9 @@ void wxVListBoxComboPopup::Insert( const wxString& item, int pos ) wxString strValue; if ( !(m_combo->GetWindowStyle() & wxCB_READONLY) && m_combo->GetValue() == item ) + { m_value = pos; + } m_strings.Insert(item,pos); @@ -458,6 +492,11 @@ void wxVListBoxComboPopup::SetSelection( int item ) wxVListBox::SetSelection(item); } +int wxVListBoxComboPopup::GetSelection() const +{ + return m_value; +} + void wxVListBoxComboPopup::SetStringValue( const wxString& value ) { int index = m_strings.Index(value); @@ -504,13 +543,16 @@ wxSize wxVListBoxComboPopup::GetAdjustedSize( int minWidth, int prefHeight, int height+2); } -void wxVListBoxComboPopup::Populate( int n, const wxString choices[] ) +//void wxVListBoxComboPopup::Populate( int n, const wxString choices[] ) +void wxVListBoxComboPopup::Populate( const wxArrayString& choices ) { int i; + int n = choices.GetCount(); + for ( i=0; iPopulate(n,choices); + int i; + for ( i=0; iClearClientDatas(); } +void wxOwnerDrawnComboBox::SetPopupControl( wxComboPopup* popup ) +{ + if ( !popup ) + { + popup = new wxVListBoxComboPopup(); + } + + wxComboControl::SetPopupControl(popup); + + wxASSERT(popup); + m_popupInterface = (wxVListBoxComboPopup*) popup; + + // Add initial choices to the wxVListBox + if ( !m_popupInterface->GetCount() ) + { + //m_popupInterface->Populate(m_initChs.GetCount(),m_initChs.GetStrings()); + m_popupInterface->Populate(m_initChs); + m_initChs.Clear(); + } +} + // ---------------------------------------------------------------------------- // wxOwnerDrawnComboBox item manipulation methods // ---------------------------------------------------------------------------- void wxOwnerDrawnComboBox::Clear() { - wxASSERT( m_popupInterface ); + EnsurePopupControl(); m_popupInterface->Clear(); @@ -648,7 +710,7 @@ void wxOwnerDrawnComboBox::Delete(unsigned int n) unsigned int wxOwnerDrawnComboBox::GetCount() const { - wxASSERT( m_popupInterface ); + wxASSERT_MSG( m_popupInterface, wxT("no popup interface") ); return m_popupInterface->GetCount(); } @@ -666,14 +728,14 @@ void wxOwnerDrawnComboBox::SetString(unsigned int n, const wxString& s) int wxOwnerDrawnComboBox::FindString(const wxString& s) const { - wxASSERT( m_popupInterface ); + wxASSERT_MSG( m_popupInterface, wxT("no popup interface") ); return m_popupInterface->FindString(s); } void wxOwnerDrawnComboBox::Select(int n) { wxCHECK_RET( (n >= -1) && (n < (int)GetCount()), _T("invalid index in wxOwnerDrawnComboBox::Select") ); - wxASSERT( m_popupInterface ); + EnsurePopupControl(); m_popupInterface->SetSelection(n); @@ -692,13 +754,14 @@ void wxOwnerDrawnComboBox::Select(int n) int wxOwnerDrawnComboBox::GetSelection() const { - wxASSERT( m_popupInterface ); + wxASSERT_MSG( m_popupInterface, wxT("no popup interface") ); return m_popupInterface->GetSelection(); } int wxOwnerDrawnComboBox::DoAppend(const wxString& item) { - wxASSERT( m_popupInterface ); + EnsurePopupControl(); + wxASSERT(m_popupInterface); return m_popupInterface->Append(item); } @@ -707,6 +770,7 @@ int wxOwnerDrawnComboBox::DoInsert(const wxString& item, unsigned int pos) wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT), -1, wxT("can't insert into sorted list")); wxCHECK_MSG((pos>=0) && (pos<=GetCount()), -1, wxT("invalid index")); + EnsurePopupControl(); m_popupInterface->Insert(item,pos); return pos; @@ -714,13 +778,13 @@ int wxOwnerDrawnComboBox::DoInsert(const wxString& item, unsigned int pos) void wxOwnerDrawnComboBox::DoSetItemClientData(unsigned int n, void* clientData) { - wxASSERT(m_popupInterface); + EnsurePopupControl(); m_popupInterface->SetItemClientData(n,clientData,m_clientDataItemsType); } void* wxOwnerDrawnComboBox::DoGetItemClientData(unsigned int n) const { - wxASSERT(m_popupInterface); + wxASSERT_MSG( m_popupInterface, wxT("no popup interface") ); return m_popupInterface->GetItemClientData(n); } diff --git a/src/msw/combo.cpp b/src/msw/combo.cpp index b006217757..34c40001a7 100644 --- a/src/msw/combo.cpp +++ b/src/msw/combo.cpp @@ -454,7 +454,7 @@ void wxComboControl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) DrawButton(dc,rectb,drawButBg); // paint required portion on the control - if ( !m_text || m_widthCustomPaint ) + if ( (!m_text || m_widthCustomPaint) ) { wxASSERT( m_widthCustomPaint >= 0 ); @@ -466,7 +466,10 @@ void wxComboControl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) dc.SetFont( GetFont() ); dc.SetClippingRegion(rect); - m_popupInterface->PaintComboControl(dc,rect); + if ( m_popupInterface ) + m_popupInterface->PaintComboControl(dc,rect); + else + wxComboPopup::DefaultPaintComboControl(this,dc,rect); } } diff --git a/src/univ/combobox.cpp b/src/univ/combobox.cpp index 44d250585a..b884e8482d 100644 --- a/src/univ/combobox.cpp +++ b/src/univ/combobox.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // Name: src/univ/combobox.cpp -// Purpose: wxComboControl and wxComboBox implementation +// Purpose: wxComboBox implementation // Author: Vadim Zeitlin // Modified by: // Created: 15.12.00