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 the controls now, don't leave them alive even though they would 
 166     // still be eventually deleted by our parent - but it will be too late, the 
 167     // user code expects them to be gone now 
 168     if (m_text 
!= NULL
) { 
 172     if (m_choice 
!= NULL
) { 
 179 // ---------------------------------------------------------------------------- 
 181 // ---------------------------------------------------------------------------- 
 183 wxSize 
wxComboBox::DoGetBestSize() const 
 185     wxSize size 
= m_choice
->GetBestSize(); 
 187     if ( m_text 
!= NULL 
) 
 189         wxSize  sizeText 
= m_text
->GetBestSize(); 
 191         size
.x 
= POPUPWIDTH 
+ sizeText
.x 
+ MARGIN
; 
 197 void wxComboBox::DoMoveWindow(int x
, int y
, int width
, int height
) { 
 198     height 
= POPUPHEIGHT
; 
 200     wxControl::DoMoveWindow(x
, y
, width
, height
); 
 202     if ( m_text 
== NULL 
) 
 204         m_choice
->SetSize(0, 0 , width
, -1); 
 208         wxCoord wText 
= width 
- POPUPWIDTH 
- MARGIN
; 
 209         m_text
->SetSize(0, 0, wText
, height
); 
 210         m_choice
->SetSize(0 + wText 
+ MARGIN
, 0, POPUPWIDTH
, -1); 
 216 // ---------------------------------------------------------------------------- 
 217 // operations forwarded to the subcontrols 
 218 // ---------------------------------------------------------------------------- 
 220 bool wxComboBox::Enable(bool enable
) 
 222     if ( !wxControl::Enable(enable
) ) 
 228 bool wxComboBox::Show(bool show
) 
 230     if ( !wxControl::Show(show
) ) 
 236 void wxComboBox::SetFocus() 
 238     if ( m_text 
!= NULL
) { 
 244 void wxComboBox::DelegateTextChanged( const wxString
& value 
) 
 246     SetStringSelection( value 
); 
 250 void wxComboBox::DelegateChoice( const wxString
& value 
) 
 252     SetStringSelection( value 
); 
 256 bool wxComboBox::Create(wxWindow 
*parent
, wxWindowID id
, 
 257            const wxString
& value
, 
 260            int n
, const wxString choices
[], 
 262            const wxValidator
& validator
, 
 263            const wxString
& name
) 
 265     if ( !wxControl::Create(parent
, id
, wxDefaultPosition
, wxDefaultSize
, style 
, 
 266                             wxDefaultValidator
, name
) ) 
 271     m_choice 
= new wxComboBoxChoice(this, style 
); 
 274     if ( style 
& wxCB_READONLY 
) 
 280         m_text 
= new wxComboBoxText(this); 
 281         if ( size
.y 
== -1 ) { 
 282           csize
.y 
= m_text
->GetSize().y 
; 
 286     DoSetSize(pos
.x
, pos
.y
, csize
.x
, csize
.y
); 
 288     for ( int i 
= 0 ; i 
< n 
; i
++ ) 
 290         m_choice
->DoAppend( choices
[ i 
] ); 
 296 wxString 
wxComboBox::GetValue() const 
 300     if ( m_text 
== NULL 
) 
 302         result 
= m_choice
->GetString( m_choice
->GetSelection() ); 
 306         result 
= m_text
->GetValue(); 
 312 void wxComboBox::SetValue(const wxString
& value
) 
 314     int s 
= FindString (value
); 
 315     if (s 
== wxNOT_FOUND 
&& !HasFlag(wxCB_READONLY
) ) 
 317         m_choice
->Append(value
) ; 
 319     SetStringSelection( value 
) ; 
 322 // Clipboard operations 
 323 void wxComboBox::Copy() 
 325     if ( m_text 
!= NULL 
) 
 331 void wxComboBox::Cut() 
 333     if ( m_text 
!= NULL 
) 
 339 void wxComboBox::Paste() 
 341     if ( m_text 
!= NULL 
) 
 347 void wxComboBox::SetEditable(bool editable
) 
 349     if ( ( m_text 
== NULL 
) && editable 
) 
 351         m_text 
= new wxComboBoxText( this ); 
 353     else if ( ( m_text 
!= NULL 
) && !editable 
) 
 359     int currentX
, currentY
; 
 360     GetPosition( ¤tX
, ¤tY 
); 
 362     int currentW
, currentH
; 
 363     GetSize( ¤tW
, ¤tH 
); 
 365     DoMoveWindow( currentX
, currentY
, currentW
, currentH 
); 
 368 void wxComboBox::SetInsertionPoint(long pos
) 
 373 void wxComboBox::SetInsertionPointEnd() 
 378 long wxComboBox::GetInsertionPoint() const 
 384 long wxComboBox::GetLastPosition() const 
 390 void wxComboBox::Replace(long from
, long to
, const wxString
& value
) 
 395 void wxComboBox::Remove(long from
, long to
) 
 400 void wxComboBox::SetSelection(long from
, long to
) 
 405 int wxComboBox::DoAppend(const wxString
& item
)  
 407     return m_choice
->DoAppend( item 
) ; 
 410 int wxComboBox::DoInsert(const wxString
& item
, int pos
)  
 412     return m_choice
->DoInsert( item 
, pos 
) ; 
 415 void wxComboBox::DoSetItemClientData(int n
, void* clientData
)  
 417     return m_choice
->SetClientData( n 
, clientData 
) ; 
 420 void* wxComboBox::DoGetItemClientData(int n
) const 
 422     return m_choice
->GetClientData( n 
) ; 
 425 void wxComboBox::DoSetItemClientObject(int n
, wxClientData
* clientData
) 
 427     return m_choice
->SetClientObject( n 
, clientData 
) ; 
 430 wxClientData
* wxComboBox::DoGetItemClientObject(int n
) const  
 432     return m_choice
->GetClientObject( n 
) ; 
 435 void wxComboBox::Delete(int n
) 
 437     m_choice
->Delete( n 
); 
 440 void wxComboBox::Clear() 
 445 int wxComboBox::GetSelection() const 
 447     return m_choice
->GetSelection(); 
 450 void wxComboBox::SetSelection(int n
) 
 452     m_choice
->SetSelection( n 
); 
 454     if ( m_text 
!= NULL 
) 
 456         m_text
->SetValue( GetString( n 
) ); 
 460 int wxComboBox::FindString(const wxString
& s
) const 
 462     return m_choice
->FindString( s 
); 
 465 wxString 
wxComboBox::GetString(int n
) const 
 467     return m_choice
->GetString( n 
); 
 470 wxString 
wxComboBox::GetStringSelection() const 
 472     int sel 
= GetSelection (); 
 474         return wxString(this->GetString (sel
)); 
 476         return wxEmptyString
; 
 479 bool wxComboBox::SetStringSelection(const wxString
& sel
) 
 481     int s 
= FindString (sel
); 
 491 void wxComboBox::SetString(int n
, const wxString
& s
)  
 493     m_choice
->SetString( n 
, s 
) ; 
 497 void wxComboBox::MacHandleControlClick( WXWidget 
WXUNUSED(control
) , wxInt16 
WXUNUSED(controlpart
) , bool WXUNUSED(mouseStillDown
))  
 499     wxCommandEvent 
event(wxEVT_COMMAND_COMBOBOX_SELECTED
, m_windowId 
); 
 500     event
.SetInt(GetSelection()); 
 501     event
.SetEventObject(this); 
 502     event
.SetString(GetStringSelection()); 
 503     ProcessCommand(event
);