1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/univ/combobox.cpp 
   3 // Purpose:     wxComboBox implementation 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) 2000 SciTech Software, Inc. (www.scitechsoft.com) 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #include "wx/wxprec.h" 
  31     #include "wx/button.h" 
  32     #include "wx/combobox.h" 
  33     #include "wx/listbox.h" 
  34     #include "wx/textctrl.h" 
  35     #include "wx/bmpbuttn.h" 
  37     #include "wx/validate.h" 
  40 #include "wx/tooltip.h" 
  43 #include "wx/univ/renderer.h" 
  44 #include "wx/univ/inphand.h" 
  45 #include "wx/univ/theme.h" 
  47 // ---------------------------------------------------------------------------- 
  48 // wxStdComboBoxInputHandler: allows the user to open/close the combo from kbd 
  49 // ---------------------------------------------------------------------------- 
  51 class WXDLLEXPORT wxStdComboBoxInputHandler 
: public wxStdInputHandler
 
  54     wxStdComboBoxInputHandler(wxInputHandler 
*inphand
); 
  56     virtual bool HandleKey(wxInputConsumer 
*consumer
, 
  57                            const wxKeyEvent
& event
, 
  61 // ---------------------------------------------------------------------------- 
  62 // wxComboListBox is a listbox modified to be used as a popup window in a 
  64 // ---------------------------------------------------------------------------- 
  66 class wxComboListBox 
: public wxListBox
, public wxComboPopup
 
  71     virtual ~wxComboListBox(); 
  73     // implement wxComboPopup methods 
  74     virtual bool Create(wxWindow
* parent
); 
  75     virtual void SetStringValue(const wxString
& s
); 
  76     virtual wxString 
GetStringValue() const; 
  77     virtual wxWindow 
*GetControl() { return this; } 
  78     virtual void OnPopup(); 
  79     virtual wxSize 
GetAdjustedSize(int minWidth
, int prefHeight
, int maxHeight
); 
  81     // fix virtual function hiding 
  82     virtual void SetSelection(int n
) { DoSetSelection(n
, true); } 
  83     void SetSelection(int n
, bool select
) { DoSetSelection(n
, select
); } 
  85     // used to process wxUniv actions 
  86     bool PerformAction(const wxControlAction
& action
, 
  88                        const wxString
& strArg
); 
  91     // set m_clicked value from here 
  92     void OnLeftUp(wxMouseEvent
& event
); 
  95     friend class wxComboBox
; // it accesses our DoGetItemClientData() 
 100 // ---------------------------------------------------------------------------- 
 101 // event tables and such 
 102 // ---------------------------------------------------------------------------- 
 104 BEGIN_EVENT_TABLE(wxComboListBox
, wxListBox
) 
 105     EVT_LEFT_UP(wxComboListBox::OnLeftUp
) 
 108 // ============================================================================ 
 110 // ============================================================================ 
 112 // ---------------------------------------------------------------------------- 
 114 // ---------------------------------------------------------------------------- 
 116 wxComboListBox::wxComboListBox() : wxListBox(), wxComboPopup() 
 120 bool wxComboListBox::Create(wxWindow
* parent
) 
 122     if ( !wxListBox::Create(parent
, wxID_ANY
, 
 123                             wxDefaultPosition
, wxDefaultSize
, 
 126                             ( m_combo
->GetWindowStyle() & wxCB_SORT 
? wxLB_SORT 
: 0 ) ) ) 
 129     // we don't react to the mouse events outside the window at all 
 135 wxComboListBox::~wxComboListBox() 
 139 wxString 
wxComboListBox::GetStringValue() const 
 141     return wxListBox::GetStringSelection(); 
 144 void wxComboListBox::SetStringValue(const wxString
& value
) 
 146     if ( !value
.empty() ) 
 148         if (FindString(value
) != wxNOT_FOUND
) 
 149             wxListBox::SetStringSelection(value
); 
 152         wxListBox::SetSelection(-1); 
 155 void wxComboListBox::OnPopup() 
 159 bool wxComboListBox::PerformAction(const wxControlAction
& action
, 
 161                                    const wxString
& strArg
) 
 164     if ( action 
== wxACTION_LISTBOX_FIND 
) 
 166         // we don't let the listbox handle this as instead of just using the 
 167         // single key presses, as usual, we use the text ctrl value as prefix 
 168         // and this is done by wxComboCtrl itself 
 172     return wxListBox::PerformAction(action
, numArg
, strArg
); 
 175 void wxComboListBox::OnLeftUp(wxMouseEvent
& event
) 
 177     // we should dismiss the combo now 
 178     // first update the combo and close the listbox 
 180     m_combo
->SetValue(wxListBox::GetStringSelection()); 
 182     // next let the user code have the event 
 183     wxCommandEvent 
evt(wxEVT_COMBOBOX
,m_combo
->GetId()); 
 184     evt
.SetInt(wxListBox::GetSelection()); 
 185     evt
.SetEventObject(m_combo
); 
 186     m_combo
->ProcessWindowEvent(evt
); 
 191 wxSize 
wxComboListBox::GetAdjustedSize(int minWidth
, 
 192                                        int WXUNUSED(prefHeight
), 
 195     wxSize bestSize 
= wxListBox::GetBestSize(); 
 196     return wxSize(wxMax(bestSize
.x
,minWidth
), 
 197                   wxMin(bestSize
.y
,maxHeight
)); 
 200 // ---------------------------------------------------------------------------- 
 202 // ---------------------------------------------------------------------------- 
 204 void wxComboBox::Init() 
 209 wxComboBox::wxComboBox(wxWindow 
*parent
, 
 211                        const wxString
& value
, 
 214                        const wxArrayString
& choices
, 
 216                        const wxValidator
& validator
, 
 217                        const wxString
& name
) 
 221     Create(parent
, id
, value
, pos
, size
, choices
, style
, validator
, name
); 
 224 bool wxComboBox::Create(wxWindow 
*parent
, 
 226                         const wxString
& value
, 
 229                         const wxArrayString
& choices
, 
 231                         const wxValidator
& validator
, 
 232                         const wxString
& name
) 
 234     wxCArrayString 
chs(choices
); 
 236     return Create(parent
, id
, value
, pos
, size
, chs
.GetCount(), 
 237                   chs
.GetStrings(), style
, validator
, name
); 
 240 bool wxComboBox::Create(wxWindow 
*parent
, 
 242                         const wxString
& value
, 
 246                         const wxString choices
[], 
 248                         const wxValidator
& validator
, 
 249                         const wxString
& name
) 
 251     if ( !wxComboCtrl::Create(parent
, id
, value
, pos
, size
, style
, 
 257     wxComboListBox 
*combolbox 
= new wxComboListBox(); 
 258     SetPopupControl(combolbox
); 
 261     m_lbox
->Set(n
, choices
); 
 266 wxComboBox::~wxComboBox() 
 270 // ---------------------------------------------------------------------------- 
 271 // wxComboBox methods forwarded to wxTextCtrl 
 272 // ---------------------------------------------------------------------------- 
 274 wxString 
wxComboBox::DoGetValue() const 
 276     return GetTextCtrl() ? GetTextCtrl()->GetValue() : m_valueString
; 
 279 void wxComboBox::SetValue(const wxString
& value
) 
 282         GetTextCtrl()->SetValue(value
); 
 284         m_valueString 
= value
; 
 287 void wxComboBox::WriteText(const wxString
& value
) 
 289     if ( GetTextCtrl() ) GetTextCtrl()->WriteText(value
); 
 292 void wxComboBox::Copy() 
 294     if ( GetTextCtrl() ) GetTextCtrl()->Copy(); 
 297 void wxComboBox::Cut() 
 299     if ( GetTextCtrl() ) GetTextCtrl()->Cut(); 
 302 void wxComboBox::Paste() 
 304     if ( GetTextCtrl() ) GetTextCtrl()->Paste(); 
 307 void wxComboBox::SetInsertionPoint(long pos
) 
 309     if ( GetTextCtrl() ) GetTextCtrl()->SetInsertionPoint(pos
); 
 312 void wxComboBox::SetInsertionPointEnd() 
 314     if ( GetTextCtrl() ) GetTextCtrl()->SetInsertionPointEnd(); 
 317 long wxComboBox::GetInsertionPoint() const 
 320         return GetTextCtrl()->GetInsertionPoint(); 
 324 wxTextPos 
wxComboBox::GetLastPosition() const 
 327         return GetTextCtrl()->GetLastPosition(); 
 331 void wxComboBox::Replace(long from
, long to
, const wxString
& value
) 
 333     if ( GetTextCtrl() ) GetTextCtrl()->Replace(from
, to
, value
); 
 336 void wxComboBox::Remove(long from
, long to
) 
 338     if ( GetTextCtrl() ) GetTextCtrl()->Remove(from
, to
); 
 341 void wxComboBox::SetSelection(long from
, long to
) 
 343     if ( GetTextCtrl() ) GetTextCtrl()->SetSelection(from
, to
); 
 346 void wxComboBox::GetSelection(long *from
, long *to
) const 
 348     if ( GetTextCtrl() ) GetTextCtrl()->GetSelection(from
, to
); 
 351 void wxComboBox::SetEditable(bool editable
) 
 353     if ( GetTextCtrl() ) GetTextCtrl()->SetEditable(editable
); 
 356 // ---------------------------------------------------------------------------- 
 357 // wxComboBox methods forwarded to wxListBox 
 358 // ---------------------------------------------------------------------------- 
 360 void wxComboBox::DoClear() 
 363     SetValue(wxEmptyString
); 
 366 void wxComboBox::DoDeleteOneItem(unsigned int n
) 
 368     wxCHECK_RET( IsValid(n
), wxT("invalid index in wxComboBox::Delete") ); 
 370     if (GetSelection() == (int)n
) 
 371         SetValue(wxEmptyString
); 
 373     GetLBox()->Delete(n
); 
 376 unsigned int wxComboBox::GetCount() const 
 378     return GetLBox()->GetCount(); 
 381 wxString 
wxComboBox::GetString(unsigned int n
) const 
 383     wxCHECK_MSG( IsValid(n
), wxEmptyString
, wxT("invalid index in wxComboBox::GetString") ); 
 385     return GetLBox()->GetString(n
); 
 388 void wxComboBox::SetString(unsigned int n
, const wxString
& s
) 
 390     wxCHECK_RET( IsValid(n
), wxT("invalid index in wxComboBox::SetString") ); 
 392     GetLBox()->SetString(n
, s
); 
 395 int wxComboBox::FindString(const wxString
& s
, bool bCase
) const 
 397     return GetLBox()->FindString(s
, bCase
); 
 400 void wxComboBox::SetSelection(int n
) 
 402     wxCHECK_RET( (n 
== wxNOT_FOUND 
|| IsValid(n
)), wxT("invalid index in wxComboBox::Select") ); 
 404     GetLBox()->SetSelection(n
); 
 407     if ( n 
!= wxNOT_FOUND 
) 
 408         str 
= GetLBox()->GetString(n
); 
 413 int wxComboBox::GetSelection() const 
 415 #if 1 // FIXME:: What is the correct behaviour? 
 416     // if the current value isn't one of the listbox strings, return -1 
 417     return GetLBox()->GetSelection(); 
 419     // Why oh why is this done this way? 
 420     // It is not because the value displayed in the text can be found 
 421     // in the list that it is the item that is selected! 
 422     return FindString(if ( GetTextCtrl() ) GetTextCtrl()->GetValue()); 
 426 wxString 
wxComboBox::GetStringSelection() const 
 428     return GetLBox()->GetStringSelection(); 
 431 wxClientDataType 
wxComboBox::GetClientDataType() const 
 433     return GetLBox()->GetClientDataType(); 
 436 void wxComboBox::SetClientDataType(wxClientDataType clientDataItemsType
) 
 438     GetLBox()->SetClientDataType(clientDataItemsType
); 
 441 int wxComboBox::DoInsertItems(const wxArrayStringsAdapter 
& items
, 
 443                               void **clientData
, wxClientDataType type
) 
 445     return GetLBox()->DoInsertItems(items
, pos
, clientData
, type
); 
 448 void wxComboBox::DoSetItemClientData(unsigned int n
, void* clientData
) 
 450     GetLBox()->DoSetItemClientData(n
, clientData
); 
 453 void *wxComboBox::DoGetItemClientData(unsigned int n
) const 
 455     return GetLBox()->DoGetItemClientData(n
); 
 458 bool wxComboBox::IsEditable() const 
 460     return GetTextCtrl() != NULL 
&& (!HasFlag(wxCB_READONLY
) || GetTextCtrl()->IsEditable() ); 
 463 void wxComboBox::Undo() 
 466         if ( GetTextCtrl() ) GetTextCtrl()->Undo(); 
 469 void wxComboBox::Redo() 
 472         if ( GetTextCtrl() ) GetTextCtrl()->Redo(); 
 475 void wxComboBox::SelectAll() 
 477     if ( GetTextCtrl() ) GetTextCtrl()->SelectAll(); 
 480 bool wxComboBox::CanCopy() const 
 482     if (GetTextCtrl() != NULL
) 
 483         return GetTextCtrl()->CanCopy(); 
 488 bool wxComboBox::CanCut() const 
 490     if (GetTextCtrl() != NULL
) 
 491         return GetTextCtrl()->CanCut(); 
 496 bool wxComboBox::CanPaste() const 
 499         return GetTextCtrl()->CanPaste(); 
 504 bool wxComboBox::CanUndo() const 
 507         return GetTextCtrl()->CanUndo(); 
 512 bool wxComboBox::CanRedo() const 
 515         return GetTextCtrl()->CanRedo(); 
 521 // ---------------------------------------------------------------------------- 
 522 // wxStdComboBoxInputHandler 
 523 // ---------------------------------------------------------------------------- 
 525 wxStdComboBoxInputHandler::wxStdComboBoxInputHandler(wxInputHandler 
*inphand
) 
 526                          : wxStdInputHandler(inphand
) 
 530 bool wxStdComboBoxInputHandler::HandleKey(wxInputConsumer 
*consumer
, 
 531                                           const wxKeyEvent
& event
, 
 536         wxControlAction action
; 
 537         switch ( event
.GetKeyCode() ) 
 540                 action 
= wxACTION_COMBOBOX_POPUP
; 
 544                 action 
= wxACTION_COMBOBOX_DISMISS
; 
 548         if ( !action
.IsEmpty() ) 
 550             consumer
->PerformAction(action
); 
 556     return wxStdInputHandler::HandleKey(consumer
, event
, pressed
); 
 560 wxInputHandler 
*wxComboBox::GetStdInputHandler(wxInputHandler 
*handlerDef
) 
 562     static wxStdComboBoxInputHandler 
s_handler(handlerDef
); 
 567 #endif // wxUSE_COMBOBOX