X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/57306cd4fddeaaeaad2b5f4b2145370d38a57924..b736d59eb531794e6b1cef2b4997c517569ff0dd:/src/generic/odcombo.cpp diff --git a/src/generic/odcombo.cpp b/src/generic/odcombo.cpp index c4f23b9109..3a15972c13 100644 --- a/src/generic/odcombo.cpp +++ b/src/generic/odcombo.cpp @@ -4,7 +4,6 @@ // Author: Jaakko Salli // Modified by: // Created: Apr-30-2006 -// RCS-ID: $Id$ // Copyright: (c) 2005 Jaakko Salli // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -54,6 +53,7 @@ BEGIN_EVENT_TABLE(wxVListBoxComboPopup, wxVListBox) EVT_MOTION(wxVListBoxComboPopup::OnMouseMove) EVT_KEY_DOWN(wxVListBoxComboPopup::OnKey) + EVT_CHAR(wxVListBoxComboPopup::OnChar) EVT_LEFT_UP(wxVListBoxComboPopup::OnLeftClick) END_EVENT_TABLE() @@ -95,6 +95,18 @@ wxVListBoxComboPopup::~wxVListBoxComboPopup() Clear(); } +void wxVListBoxComboPopup::SetFocus() +{ + // Suppress SetFocus() warning by simply not calling it. This combo popup + // has already been designed with the assumption that SetFocus() may not + // do anything useful, so it really doesn't need to be called. +#ifdef __WXMSW__ + // +#else + wxVListBox::SetFocus(); +#endif +} + bool wxVListBoxComboPopup::LazyCreate() { // NB: There is a bug with wxVListBox that can be avoided by creating @@ -150,7 +162,7 @@ wxCoord wxVListBoxComboPopup::OnMeasureItem(size_t n) const { wxOwnerDrawnComboBox* combo = (wxOwnerDrawnComboBox*) m_combo; - wxASSERT_MSG( combo->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)), + wxASSERT_MSG( wxDynamicCast(combo, wxOwnerDrawnComboBox), wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") ); wxCoord h = combo->OnMeasureItem(n); @@ -163,7 +175,7 @@ wxCoord wxVListBoxComboPopup::OnMeasureItemWidth(size_t n) const { wxOwnerDrawnComboBox* combo = (wxOwnerDrawnComboBox*) m_combo; - wxASSERT_MSG( combo->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)), + wxASSERT_MSG( wxDynamicCast(combo, wxOwnerDrawnComboBox), wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") ); return combo->OnMeasureItemWidth(n); @@ -176,7 +188,7 @@ void wxVListBoxComboPopup::OnDrawBg( wxDC& dc, { wxOwnerDrawnComboBox* combo = (wxOwnerDrawnComboBox*) m_combo; - wxASSERT_MSG( combo->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)), + wxASSERT_MSG( wxDynamicCast(combo, wxOwnerDrawnComboBox), wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") ); if ( IsCurrent((size_t)item) && !(flags & wxODCB_PAINTING_CONTROL) ) @@ -195,7 +207,7 @@ void wxVListBoxComboPopup::OnDrawItem( wxDC& dc, const wxRect& rect, int item, i { wxOwnerDrawnComboBox* combo = (wxOwnerDrawnComboBox*) m_combo; - wxASSERT_MSG( combo->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)), + wxASSERT_MSG( wxDynamicCast(combo, wxOwnerDrawnComboBox), wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") ); combo->OnDrawItem(dc,rect,item,flags); @@ -215,7 +227,7 @@ void wxVListBoxComboPopup::DismissWithEvent() m_stringValue = wxEmptyString; if ( m_stringValue != m_combo->GetValue() ) - m_combo->SetValueWithEvent(m_stringValue); + m_combo->SetValueByUser(m_stringValue); m_value = selection; @@ -224,7 +236,7 @@ void wxVListBoxComboPopup::DismissWithEvent() void wxVListBoxComboPopup::SendComboBoxEvent( int selection ) { - wxCommandEvent evt(wxEVT_COMMAND_COMBOBOX_SELECTED,m_combo->GetId()); + wxCommandEvent evt(wxEVT_COMBOBOX,m_combo->GetId()); evt.SetEventObject(m_combo); @@ -244,7 +256,7 @@ void wxVListBoxComboPopup::SendComboBoxEvent( int selection ) } // returns true if key was consumed -bool wxVListBoxComboPopup::HandleKey( int keycode, bool saturate, wxChar unicode ) +bool wxVListBoxComboPopup::HandleKey( int keycode, bool saturate, wxChar keychar ) { const int itemCount = GetCount(); @@ -256,38 +268,47 @@ bool wxVListBoxComboPopup::HandleKey( int keycode, bool saturate, wxChar unicode int value = m_value; int comboStyle = m_combo->GetWindowStyle(); - // this is the character equivalent of the code - wxChar keychar=0; - if ((keycode >= WXK_SPACE) && (keycode <=255) && (keycode != WXK_DELETE) && wxIsprint(keycode)) + if ( keychar > 0 ) { - keychar = (wxChar)keycode; - } - else if (unicode>0) - { - keychar = unicode; + // we have character equivalent of the keycode; filter out these that + // are not printable characters + if ( !wxIsprint(keychar) ) + keychar = 0; } - if ( keycode == WXK_DOWN || keycode == WXK_RIGHT ) + const bool readOnly = (comboStyle & wxCB_READONLY) != 0; + + if ( keycode == WXK_DOWN || keycode == WXK_NUMPAD_DOWN || ( keycode == WXK_RIGHT && readOnly ) ) { value++; StopPartialCompletion(); } - else if ( keycode == WXK_UP || keycode == WXK_LEFT ) + else if ( keycode == WXK_UP || keycode == WXK_NUMPAD_UP || ( keycode == WXK_LEFT && readOnly ) ) { value--; StopPartialCompletion(); } - else if ( keycode == WXK_PAGEDOWN ) + else if ( keycode == WXK_PAGEDOWN || keycode == WXK_NUMPAD_PAGEDOWN ) { value+=10; StopPartialCompletion(); } - else if ( keycode == WXK_PAGEUP ) + else if ( keycode == WXK_PAGEUP || keycode == WXK_NUMPAD_PAGEUP ) { value-=10; StopPartialCompletion(); } - else if ( comboStyle & wxCB_READONLY ) + else if ( ( keycode == WXK_HOME || keycode == WXK_NUMPAD_HOME ) && readOnly ) + { + value=0; + StopPartialCompletion(); + } + else if ( ( keycode == WXK_END || keycode == WXK_NUMPAD_END ) && readOnly ) + { + value=itemCount-1; + StopPartialCompletion(); + } + else if ( keychar && readOnly ) { // Try partial completion @@ -350,10 +371,14 @@ bool wxVListBoxComboPopup::HandleKey( int keycode, bool saturate, wxChar unicode // (good for consistency) return true; - m_value = value; - if ( value >= 0 ) - m_combo->SetValue(m_strings[value]); + m_combo->ChangeValue(m_strings[value]); + + // The m_combo->SetValue() call above sets m_value to the index of this + // string. But if there are more identical string, the index is of the + // first occurrence, which may be wrong, so set the index explicitly here, + // _after_ the SetValue() call. + m_value = value; SendComboBoxEvent(m_value); @@ -381,13 +406,21 @@ void wxVListBoxComboPopup::OnComboDoubleClick() void wxVListBoxComboPopup::OnComboKeyEvent( wxKeyEvent& event ) { // Saturated key movement on - if ( !HandleKey(event.GetKeyCode(),true, + if ( !HandleKey(event.GetKeyCode(), true) ) + event.Skip(); +} + +void wxVListBoxComboPopup::OnComboCharEvent( wxKeyEvent& event ) +{ + // unlike in OnComboKeyEvent, wxEVT_CHAR contains meaningful + // printable character information, so pass it #if wxUSE_UNICODE - event.GetUnicodeKey() + const wxChar charcode = event.GetUnicodeKey(); #else - 0 + const wxChar charcode = (wxChar)event.GetKeyCode(); #endif - ) ) + + if ( !HandleKey(event.GetKeyCode(), true, charcode) ) event.Skip(); } @@ -452,18 +485,31 @@ void wxVListBoxComboPopup::OnKey(wxKeyEvent& event) } else { - int comboStyle = m_combo->GetWindowStyle(); - int keycode = event.GetKeyCode(); - // Process partial completion key codes here, but not the arrow keys as the base class will do that for us - if ((comboStyle & wxCB_READONLY) && - (keycode >= WXK_SPACE) && (keycode <=255) && (keycode != WXK_DELETE) && wxIsprint(keycode)) + // completion is handled in OnChar() below + event.Skip(); + } +} + +void wxVListBoxComboPopup::OnChar(wxKeyEvent& event) +{ + if ( m_combo->GetWindowStyle() & wxCB_READONLY ) + { + // Process partial completion key codes here, but not the arrow keys as + // the base class will do that for us +#if wxUSE_UNICODE + const wxChar charcode = event.GetUnicodeKey(); +#else + const wxChar charcode = (wxChar)event.GetKeyCode(); +#endif + if ( wxIsprint(charcode) ) { - OnComboKeyEvent(event); + OnComboCharEvent(event); SetSelection(m_value); // ensure the highlight bar moves + return; // don't skip the event } - else - event.Skip(); } + + event.Skip(); } void wxVListBoxComboPopup::Insert( const wxString& item, int pos ) @@ -477,7 +523,7 @@ void wxVListBoxComboPopup::Insert( const wxString& item, int pos ) } m_strings.Insert(item,pos); - if ( m_clientDatas.size() >= pos ) + if ( (int)m_clientDatas.size() >= pos ) m_clientDatas.Insert(NULL, pos); m_widths.Insert(-1,pos); @@ -500,7 +546,7 @@ int wxVListBoxComboPopup::Append(const wxString& item) for ( i=0; iGetFont(); dc.SetFont(m_useFont); for ( i=0; i= totalHeight ) { height = totalHeight; @@ -805,7 +868,7 @@ void wxVListBoxComboPopup::Populate( const wxArrayString& choices ) // Find initial selection wxString strValue = m_combo->GetValue(); - if ( strValue.length() ) + if ( !strValue.empty() ) m_value = m_strings.Index(strValue); } @@ -817,21 +880,6 @@ void wxVListBoxComboPopup::Populate( const wxArrayString& choices ) BEGIN_EVENT_TABLE(wxOwnerDrawnComboBox, wxComboCtrl) END_EVENT_TABLE() - -#if wxUSE_EXTENDED_RTTI -IMPLEMENT_DYNAMIC_CLASS2_XTI(wxOwnerDrawnComboBox, wxComboCtrl, wxControlWithItems, "wx/odcombo.h") - -wxBEGIN_PROPERTIES_TABLE(wxOwnerDrawnComboBox) -wxEND_PROPERTIES_TABLE() - -wxBEGIN_HANDLERS_TABLE(wxOwnerDrawnComboBox) -wxEND_HANDLERS_TABLE() - -wxCONSTRUCTOR_5( wxOwnerDrawnComboBox , wxWindow* , Parent , wxWindowID , Id , wxString , Value , wxPoint , Position , wxSize , Size ) -#else -IMPLEMENT_DYNAMIC_CLASS2(wxOwnerDrawnComboBox, wxComboCtrl, wxControlWithItems) -#endif - void wxOwnerDrawnComboBox::Init() { } @@ -857,7 +905,6 @@ wxOwnerDrawnComboBox::wxOwnerDrawnComboBox(wxWindow *parent, long style, const wxValidator& validator, const wxString& name) - : wxComboCtrl() { Init(); @@ -943,15 +990,22 @@ void wxOwnerDrawnComboBox::DoClear() GetVListBoxComboPopup()->Clear(); + // NB: This really needs to be SetValue() instead of ChangeValue(), + // as wxTextEntry API expects an event to be sent. SetValue(wxEmptyString); } +void wxOwnerDrawnComboBox::Clear() +{ + DoClear(); +} + void wxOwnerDrawnComboBox::DoDeleteOneItem(unsigned int n) { - wxCHECK_RET( IsValid(n), _T("invalid index in wxOwnerDrawnComboBox::Delete") ); + wxCHECK_RET( IsValid(n), wxT("invalid index in wxOwnerDrawnComboBox::Delete") ); if ( GetSelection() == (int) n ) - SetValue(wxEmptyString); + ChangeValue(wxEmptyString); GetVListBoxComboPopup()->Delete(n); } @@ -966,7 +1020,7 @@ unsigned int wxOwnerDrawnComboBox::GetCount() const wxString wxOwnerDrawnComboBox::GetString(unsigned int n) const { - wxCHECK_MSG( IsValid(n), wxEmptyString, _T("invalid index in wxOwnerDrawnComboBox::GetString") ); + wxCHECK_MSG( IsValid(n), wxEmptyString, wxT("invalid index in wxOwnerDrawnComboBox::GetString") ); if ( !m_popupInterface ) return m_initChs.Item(n); @@ -978,7 +1032,7 @@ void wxOwnerDrawnComboBox::SetString(unsigned int n, const wxString& s) { EnsurePopupControl(); - wxCHECK_RET( IsValid(n), _T("invalid index in wxOwnerDrawnComboBox::SetString") ); + wxCHECK_RET( IsValid(n), wxT("invalid index in wxOwnerDrawnComboBox::SetString") ); GetVListBoxComboPopup()->SetString(n,s); } @@ -995,7 +1049,7 @@ void wxOwnerDrawnComboBox::Select(int n) { EnsurePopupControl(); - wxCHECK_RET( (n == wxNOT_FOUND) || IsValid(n), _T("invalid index in wxOwnerDrawnComboBox::Select") ); + wxCHECK_RET( (n == wxNOT_FOUND) || IsValid(n), wxT("invalid index in wxOwnerDrawnComboBox::Select") ); GetVListBoxComboPopup()->SetSelection(n); @@ -1005,7 +1059,7 @@ void wxOwnerDrawnComboBox::Select(int n) // Refresh text portion in control if ( m_text ) - m_text->SetValue( str ); + m_text->ChangeValue( str ); else m_valueString = str; @@ -1020,6 +1074,11 @@ int wxOwnerDrawnComboBox::GetSelection() const return GetVListBoxComboPopup()->GetSelection(); } +void wxOwnerDrawnComboBox::GetSelection(long *from, long *to) const +{ + wxComboCtrl::GetSelection(from, to); +} + int wxOwnerDrawnComboBox::DoInsertItems(const wxArrayStringsAdapter& items, unsigned int pos, void **clientData, @@ -1035,7 +1094,7 @@ int wxOwnerDrawnComboBox::DoInsertItems(const wxArrayStringsAdapter& items, for ( unsigned int i = 0; i < count; ++i ) { - int n = GetVListBoxComboPopup()->Append(items[i]); + n = GetVListBoxComboPopup()->Append(items[i]); AssignNewItemClientData(n, clientData, i, type); } @@ -1080,8 +1139,21 @@ void wxOwnerDrawnComboBox::OnDrawItem( wxDC& dc, { if ( flags & wxODCB_PAINTING_CONTROL ) { - dc.DrawText( GetValue(), - rect.x + GetTextIndent(), + wxString text; + + if ( !ShouldUseHintText() ) + { + text = GetValue(); + } + else + { + text = GetHint(); + wxColour col = wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT); + dc.SetTextForeground(col); + } + + dc.DrawText( text, + rect.x + GetMargins().x, (rect.height-dc.GetCharHeight())/2 + rect.y ); } else @@ -1100,6 +1172,22 @@ wxCoord wxOwnerDrawnComboBox::OnMeasureItemWidth( size_t WXUNUSED(item) ) const return -1; } +wxSize wxOwnerDrawnComboBox::DoGetBestSize() const +{ + wxSize best( wxComboCtrlBase::DoGetBestSize() ); + + if ( GetCount() > 0 ) + { + wxOwnerDrawnComboBox* odc = const_cast(this); + best.x = odc->GetWidestItemWidth(); + // TODO: this class may also have GetHightestItemHeight() and + // GetHightestItem() methods, and so set the whole (edit part + arrow) + // control's height according with this max height, not only max width. + } + + return GetSizeFromTextSize(best.x); +} + void wxOwnerDrawnComboBox::OnDrawBackground(wxDC& dc, const wxRect& rect, int WXUNUSED(item),