1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxComboBox class 
   4 // Author:      Stefan Csomor 
   8 // Copyright:   (c) Stefan Csomor 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  13 #pragma implementation "combobox.h" 
  16 #include "wx/combobox.h" 
  17 #include "wx/button.h" 
  19 #include "wx/mac/uma.h" 
  21 #if !USE_SHARED_LIBRARY 
  22 IMPLEMENT_DYNAMIC_CLASS(wxComboBox
, wxControl
) 
  25 // composite combobox implementation by Dan "Bud" Keith bud@otsys.com 
  28 static int nextPopUpMenuId 
= 1000 ; 
  29 MenuHandle 
NewUniqueMenu() 
  31   MenuHandle handle 
= NewMenu( nextPopUpMenuId 
, "\pMenu" ) ; 
  37 // ---------------------------------------------------------------------------- 
  39 // ---------------------------------------------------------------------------- 
  41 // the margin between the text control and the choice 
  42 static const wxCoord MARGIN 
= 2; 
  43 static const int    POPUPWIDTH 
= 18; 
  44 static const int    POPUPHEIGHT 
= 23; 
  47 // ---------------------------------------------------------------------------- 
  48 // wxComboBoxText: text control forwards events to combobox 
  49 // ---------------------------------------------------------------------------- 
  51 class wxComboBoxText 
: public wxTextCtrl
 
  54     wxComboBoxText( wxComboBox 
* cb 
) 
  55         : wxTextCtrl( cb 
, 1 ) 
  61     void OnChar( wxKeyEvent
& event 
) 
  63         if ( event
.GetKeyCode() == WXK_RETURN 
) 
  65             wxString value 
= GetValue(); 
  67             if ( m_cb
->GetCount() == 0 ) 
  69                 // make Enter generate "selected" event if there is only one item 
  70                 // in the combobox - without it, it's impossible to select it at 
  72                 wxCommandEvent 
event( wxEVT_COMMAND_COMBOBOX_SELECTED
, m_cb
->GetId() ); 
  74                 event
.SetString( value 
); 
  75                 event
.SetEventObject( m_cb 
); 
  76                 m_cb
->GetEventHandler()->ProcessEvent( event 
); 
  80                 // add the item to the list if it's not there yet 
  81                 if ( m_cb
->FindString(value
) == wxNOT_FOUND 
) 
  84                     m_cb
->SetStringSelection(value
); 
  86                     // and generate the selected event for it 
  87                     wxCommandEvent 
event( wxEVT_COMMAND_COMBOBOX_SELECTED
, m_cb
->GetId() ); 
  88                     event
.SetInt( m_cb
->GetCount() - 1 ); 
  89                     event
.SetString( value 
); 
  90                     event
.SetEventObject( m_cb 
); 
  91                     m_cb
->GetEventHandler()->ProcessEvent( event 
); 
  94                 // This will invoke the dialog default action, such 
  95                 // as the clicking the default button. 
  97                 wxWindow 
*parent 
= GetParent(); 
  98                 while( parent 
&& !parent
->IsTopLevel() && parent
->GetDefaultItem() == NULL 
) { 
  99                     parent 
= parent
->GetParent() ; 
 101                 if ( parent 
&& parent
->GetDefaultItem() ) 
 103                     wxButton 
*def 
= wxDynamicCast(parent
->GetDefaultItem(), 
 105                     if ( def 
&& def
->IsEnabled() ) 
 107                         wxCommandEvent 
event(wxEVT_COMMAND_BUTTON_CLICKED
, def
->GetId() ); 
 108                         event
.SetEventObject(def
); 
 124     DECLARE_EVENT_TABLE() 
 127 BEGIN_EVENT_TABLE(wxComboBoxText
, wxTextCtrl
) 
 128     EVT_CHAR( wxComboBoxText::OnChar
) 
 131 class wxComboBoxChoice 
: public wxChoice
 
 134     wxComboBoxChoice(wxComboBox 
*cb
, int style
) 
 141     void OnChoice( wxCommandEvent
& e 
) 
 143         wxString    s 
= e
.GetString(); 
 145         m_cb
->DelegateChoice( s 
); 
 146         wxCommandEvent 
event2(wxEVT_COMMAND_COMBOBOX_SELECTED
, m_cb
->GetId() ); 
 147         event2
.SetInt(m_cb
->GetSelection()); 
 148         event2
.SetEventObject(m_cb
); 
 149         event2
.SetString(m_cb
->GetStringSelection()); 
 150         m_cb
->ProcessCommand(event2
); 
 156     DECLARE_EVENT_TABLE() 
 159 BEGIN_EVENT_TABLE(wxComboBoxChoice
, wxChoice
) 
 160     EVT_CHOICE(-1, wxComboBoxChoice::OnChoice
) 
 163 wxComboBox::~wxComboBox() 
 165     // delete client objects 
 168     // delete the controls now, don't leave them alive even though they would 
 169     // still be eventually deleted by our parent - but it will be too late, the 
 170     // user code expects them to be gone now 
 171     if (m_text 
!= NULL
) { 
 175     if (m_choice 
!= NULL
) { 
 182 // ---------------------------------------------------------------------------- 
 184 // ---------------------------------------------------------------------------- 
 186 wxSize 
wxComboBox::DoGetBestSize() const 
 188     wxSize size 
= m_choice
->GetBestSize(); 
 190     if ( m_text 
!= NULL 
) 
 192         wxSize  sizeText 
= m_text
->GetBestSize(); 
 194         size
.x 
= POPUPWIDTH 
+ sizeText
.x 
+ MARGIN
; 
 200 void wxComboBox::DoMoveWindow(int x
, int y
, int width
, int height
) { 
 201     height 
= POPUPHEIGHT
; 
 203     wxControl::DoMoveWindow(x
, y
, width
, height
); 
 205     if ( m_text 
== NULL 
) 
 207         m_choice
->SetSize(0, 0 , width
, -1); 
 211         wxCoord wText 
= width 
- POPUPWIDTH 
- MARGIN
; 
 212         m_text
->SetSize(0, 0, wText
, height
); 
 213         m_choice
->SetSize(0 + wText 
+ MARGIN
, 0, POPUPWIDTH
, -1); 
 219 // ---------------------------------------------------------------------------- 
 220 // operations forwarded to the subcontrols 
 221 // ---------------------------------------------------------------------------- 
 223 bool wxComboBox::Enable(bool enable
) 
 225     if ( !wxControl::Enable(enable
) ) 
 231 bool wxComboBox::Show(bool show
) 
 233     if ( !wxControl::Show(show
) ) 
 239 void wxComboBox::SetFocus() 
 241     if ( m_text 
!= NULL
) { 
 247 void wxComboBox::DelegateTextChanged( const wxString
& value 
) 
 249     SetStringSelection( value 
); 
 253 void wxComboBox::DelegateChoice( const wxString
& value 
) 
 255     SetStringSelection( value 
); 
 259 bool wxComboBox::Create(wxWindow 
*parent
, wxWindowID id
, 
 260            const wxString
& value
, 
 263            const wxArrayString
& choices
, 
 265            const wxValidator
& validator
, 
 266            const wxString
& name
) 
 268     wxCArrayString 
chs( choices 
); 
 270     return Create( parent
, id
, value
, pos
, size
, chs
.GetCount(), 
 271                    chs
.GetStrings(), style
, validator
, name 
); 
 275 bool wxComboBox::Create(wxWindow 
*parent
, wxWindowID id
, 
 276            const wxString
& value
, 
 279            int n
, const wxString choices
[], 
 281            const wxValidator
& validator
, 
 282            const wxString
& name
) 
 284     if ( !wxControl::Create(parent
, id
, wxDefaultPosition
, wxDefaultSize
, style 
, 
 285                             wxDefaultValidator
, name
) ) 
 290     m_choice 
= new wxComboBoxChoice(this, style 
); 
 293     if ( style 
& wxCB_READONLY 
) 
 299         m_text 
= new wxComboBoxText(this); 
 300         if ( size
.y 
== -1 ) { 
 301           csize
.y 
= m_text
->GetSize().y 
; 
 305     DoSetSize(pos
.x
, pos
.y
, csize
.x
, csize
.y
); 
 307     for ( int i 
= 0 ; i 
< n 
; i
++ ) 
 309         m_choice
->DoAppend( choices
[ i 
] ); 
 315 wxString 
wxComboBox::GetValue() const 
 319     if ( m_text 
== NULL 
) 
 321         result 
= m_choice
->GetString( m_choice
->GetSelection() ); 
 325         result 
= m_text
->GetValue(); 
 331 void wxComboBox::SetValue(const wxString
& value
) 
 333     int s 
= FindString (value
); 
 334     if (s 
== wxNOT_FOUND 
&& !HasFlag(wxCB_READONLY
) ) 
 336         m_choice
->Append(value
) ; 
 338     SetStringSelection( value 
) ; 
 341 // Clipboard operations 
 342 void wxComboBox::Copy() 
 344     if ( m_text 
!= NULL 
) 
 350 void wxComboBox::Cut() 
 352     if ( m_text 
!= NULL 
) 
 358 void wxComboBox::Paste() 
 360     if ( m_text 
!= NULL 
) 
 366 void wxComboBox::SetEditable(bool editable
) 
 368     if ( ( m_text 
== NULL 
) && editable 
) 
 370         m_text 
= new wxComboBoxText( this ); 
 372     else if ( ( m_text 
!= NULL 
) && !editable 
) 
 378     int currentX
, currentY
; 
 379     GetPosition( ¤tX
, ¤tY 
); 
 381     int currentW
, currentH
; 
 382     GetSize( ¤tW
, ¤tH 
); 
 384     DoMoveWindow( currentX
, currentY
, currentW
, currentH 
); 
 387 void wxComboBox::SetInsertionPoint(long pos
) 
 392 void wxComboBox::SetInsertionPointEnd() 
 397 long wxComboBox::GetInsertionPoint() const 
 403 wxTextPos 
wxComboBox::GetLastPosition() const 
 409 void wxComboBox::Replace(long from
, long to
, const wxString
& value
) 
 414 void wxComboBox::Remove(long from
, long to
) 
 419 void wxComboBox::SetSelection(long from
, long to
) 
 424 int wxComboBox::DoAppend(const wxString
& item
) 
 426     return m_choice
->DoAppend( item 
) ; 
 429 int wxComboBox::DoInsert(const wxString
& item
, int pos
) 
 431     return m_choice
->DoInsert( item 
, pos 
) ; 
 434 void wxComboBox::DoSetItemClientData(int n
, void* clientData
) 
 436     return m_choice
->DoSetItemClientData( n 
, clientData 
) ; 
 439 void* wxComboBox::DoGetItemClientData(int n
) const 
 441     return m_choice
->DoGetItemClientData( n 
) ; 
 444 void wxComboBox::DoSetItemClientObject(int n
, wxClientData
* clientData
) 
 446     return m_choice
->DoSetItemClientObject( n 
, clientData 
) ; 
 449 wxClientData
* wxComboBox::DoGetItemClientObject(int n
) const 
 451     return m_choice
->DoGetItemClientObject( n 
) ; 
 454 void wxComboBox::FreeData() 
 456     if ( HasClientObjectData() ) 
 458         size_t count 
= GetCount(); 
 459         for ( size_t n 
= 0; n 
< count
; n
++ ) 
 461             SetClientObject( n
, NULL 
); 
 466 void wxComboBox::Delete(int n
) 
 468     // force client object deletion 
 469     if( HasClientObjectData() ) 
 470         SetClientObject( n
, NULL 
); 
 471     m_choice
->Delete( n 
); 
 474 void wxComboBox::Clear() 
 480 int wxComboBox::GetSelection() const 
 482     return m_choice
->GetSelection(); 
 485 void wxComboBox::SetSelection(int n
) 
 487     m_choice
->SetSelection( n 
); 
 489     if ( m_text 
!= NULL 
) 
 491         m_text
->SetValue( GetString( n 
) ); 
 495 int wxComboBox::FindString(const wxString
& s
) const 
 497     return m_choice
->FindString( s 
); 
 500 wxString 
wxComboBox::GetString(int n
) const 
 502     return m_choice
->GetString( n 
); 
 505 wxString 
wxComboBox::GetStringSelection() const 
 507     int sel 
= GetSelection (); 
 509         return wxString(this->GetString (sel
)); 
 511         return wxEmptyString
; 
 514 void wxComboBox::SetString(int n
, const wxString
& s
) 
 516     m_choice
->SetString( n 
, s 
) ; 
 519 bool wxComboBox::IsEditable() const 
 521     return m_text 
!= NULL 
&& !HasFlag(wxCB_READONLY
); 
 524 void wxComboBox::Undo() 
 530 void wxComboBox::Redo() 
 536 void wxComboBox::SelectAll() 
 542 bool wxComboBox::CanCopy() const 
 545         return m_text
->CanCopy(); 
 550 bool wxComboBox::CanCut() const 
 553         return m_text
->CanCut(); 
 558 bool wxComboBox::CanPaste() const 
 561         return m_text
->CanPaste(); 
 566 bool wxComboBox::CanUndo() const 
 569         return m_text
->CanUndo(); 
 574 bool wxComboBox::CanRedo() const 
 577         return m_text
->CanRedo(); 
 582 void wxComboBox::MacHandleControlClick( WXWidget 
WXUNUSED(control
) , wxInt16 
WXUNUSED(controlpart
) , bool WXUNUSED(mouseStillDown
)) 
 584     wxCommandEvent 
event(wxEVT_COMMAND_COMBOBOX_SELECTED
, m_windowId 
); 
 585     event
.SetInt(GetSelection()); 
 586     event
.SetEventObject(this); 
 587     event
.SetString(GetStringSelection()); 
 588     ProcessCommand(event
);