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 IMPLEMENT_DYNAMIC_CLASS2(wxComboBox, wxControl, wxComboCtrl)
110 // ============================================================================
112 // ============================================================================
114 // ----------------------------------------------------------------------------
116 // ----------------------------------------------------------------------------
118 wxComboListBox::wxComboListBox() : wxListBox(), wxComboPopup()
122 bool wxComboListBox::Create(wxWindow* parent)
124 if ( !wxListBox::Create(parent, wxID_ANY,
125 wxDefaultPosition, wxDefaultSize,
128 ( m_combo->GetWindowStyle() & wxCB_SORT ? wxLB_SORT : 0 ) ) )
131 // we don't react to the mouse events outside the window at all
137 wxComboListBox::~wxComboListBox()
141 wxString wxComboListBox::GetStringValue() const
143 return wxListBox::GetStringSelection();
146 void wxComboListBox::SetStringValue(const wxString& value)
148 if ( !value.empty() )
150 if (FindString(value) != wxNOT_FOUND)
151 wxListBox::SetStringSelection(value);
154 wxListBox::SetSelection(-1);
157 void wxComboListBox::OnPopup()
161 bool wxComboListBox::PerformAction(const wxControlAction& action,
163 const wxString& strArg)
166 if ( action == wxACTION_LISTBOX_FIND )
168 // we don't let the listbox handle this as instead of just using the
169 // single key presses, as usual, we use the text ctrl value as prefix
170 // and this is done by wxComboCtrl itself
174 return wxListBox::PerformAction(action, numArg, strArg);
177 void wxComboListBox::OnLeftUp(wxMouseEvent& event)
179 // we should dismiss the combo now
180 // first update the combo and close the listbox
182 m_combo->SetValue(wxListBox::GetStringSelection());
184 // next let the user code have the event
185 wxCommandEvent evt(wxEVT_COMMAND_COMBOBOX_SELECTED,m_combo->GetId());
186 evt.SetInt(wxListBox::GetSelection());
187 evt.SetEventObject(m_combo);
188 m_combo->ProcessWindowEvent(evt);
193 wxSize wxComboListBox::GetAdjustedSize(int minWidth,
194 int WXUNUSED(prefHeight),
197 wxSize bestSize = wxListBox::GetBestSize();
198 return wxSize(wxMax(bestSize.x,minWidth),
199 wxMin(bestSize.y,maxHeight));
202 // ----------------------------------------------------------------------------
204 // ----------------------------------------------------------------------------
206 void wxComboBox::Init()
211 wxComboBox::wxComboBox(wxWindow *parent,
213 const wxString& value,
216 const wxArrayString& choices,
218 const wxValidator& validator,
219 const wxString& name)
223 Create(parent, id, value, pos, size, choices, style, validator, name);
226 bool wxComboBox::Create(wxWindow *parent,
228 const wxString& value,
231 const wxArrayString& choices,
233 const wxValidator& validator,
234 const wxString& name)
236 wxCArrayString chs(choices);
238 return Create(parent, id, value, pos, size, chs.GetCount(),
239 chs.GetStrings(), style, validator, name);
242 bool wxComboBox::Create(wxWindow *parent,
244 const wxString& value,
248 const wxString choices[],
250 const wxValidator& validator,
251 const wxString& name)
253 if ( !wxComboCtrl::Create(parent, id, value, pos, size, style,
259 wxComboListBox *combolbox = new wxComboListBox();
260 SetPopupControl(combolbox);
263 m_lbox->Set(n, choices);
268 wxComboBox::~wxComboBox()
272 // ----------------------------------------------------------------------------
273 // wxComboBox methods forwarded to wxTextCtrl
274 // ----------------------------------------------------------------------------
276 wxString wxComboBox::DoGetValue() const
278 return wxComboCtrl::GetValue();
281 void wxComboBox::SetValue(const wxString& value)
283 wxComboCtrl::SetValue(value);
286 void wxComboBox::WriteText(const wxString& value)
288 if ( GetTextCtrl() ) GetTextCtrl()->WriteText(value);
291 void wxComboBox::Copy()
293 if ( GetTextCtrl() ) GetTextCtrl()->Copy();
296 void wxComboBox::Cut()
298 if ( GetTextCtrl() ) GetTextCtrl()->Cut();
301 void wxComboBox::Paste()
303 if ( GetTextCtrl() ) GetTextCtrl()->Paste();
306 void wxComboBox::SetInsertionPoint(long pos)
308 if ( GetTextCtrl() ) GetTextCtrl()->SetInsertionPoint(pos);
311 void wxComboBox::SetInsertionPointEnd()
313 if ( GetTextCtrl() ) GetTextCtrl()->SetInsertionPointEnd();
316 long wxComboBox::GetInsertionPoint() const
319 return GetTextCtrl()->GetInsertionPoint();
323 wxTextPos wxComboBox::GetLastPosition() const
326 return GetTextCtrl()->GetLastPosition();
330 void wxComboBox::Replace(long from, long to, const wxString& value)
332 if ( GetTextCtrl() ) GetTextCtrl()->Replace(from, to, value);
335 void wxComboBox::Remove(long from, long to)
337 if ( GetTextCtrl() ) GetTextCtrl()->Remove(from, to);
340 void wxComboBox::SetSelection(long from, long to)
342 if ( GetTextCtrl() ) GetTextCtrl()->SetSelection(from, to);
345 void wxComboBox::GetSelection(long *from, long *to) const
347 if ( GetTextCtrl() ) GetTextCtrl()->GetSelection(from, to);
350 void wxComboBox::SetEditable(bool editable)
352 if ( GetTextCtrl() ) GetTextCtrl()->SetEditable(editable);
355 // ----------------------------------------------------------------------------
356 // wxComboBox methods forwarded to wxListBox
357 // ----------------------------------------------------------------------------
359 void wxComboBox::DoClear()
362 if ( GetTextCtrl() ) GetTextCtrl()->SetValue(wxEmptyString);
365 void wxComboBox::DoDeleteOneItem(unsigned int n)
367 wxCHECK_RET( IsValid(n), _T("invalid index in wxComboBox::Delete") );
369 if (GetSelection() == (int)n)
370 if ( GetTextCtrl() ) GetTextCtrl()->SetValue(wxEmptyString);
372 GetLBox()->Delete(n);
375 unsigned int wxComboBox::GetCount() const
377 return GetLBox()->GetCount();
380 wxString wxComboBox::GetString(unsigned int n) const
382 wxCHECK_MSG( IsValid(n), wxEmptyString, _T("invalid index in wxComboBox::GetString") );
384 return GetLBox()->GetString(n);
387 void wxComboBox::SetString(unsigned int n, const wxString& s)
389 wxCHECK_RET( IsValid(n), _T("invalid index in wxComboBox::SetString") );
391 GetLBox()->SetString(n, s);
394 int wxComboBox::FindString(const wxString& s, bool bCase) const
396 return GetLBox()->FindString(s, bCase);
399 void wxComboBox::SetSelection(int n)
401 wxCHECK_RET( (n == wxNOT_FOUND || IsValid(n)), _T("invalid index in wxComboBox::Select") );
403 GetLBox()->SetSelection(n);
406 if ( n != wxNOT_FOUND )
407 str = GetLBox()->GetString(n);
412 int wxComboBox::GetSelection() const
414 #if 1 // FIXME:: What is the correct behavior?
415 // if the current value isn't one of the listbox strings, return -1
416 return GetLBox()->GetSelection();
418 // Why oh why is this done this way?
419 // It is not because the value displayed in the text can be found
420 // in the list that it is the item that is selected!
421 return FindString(if ( GetTextCtrl() ) GetTextCtrl()->GetValue());
425 wxString wxComboBox::GetStringSelection() const
427 return GetLBox()->GetStringSelection();
430 wxClientDataType wxComboBox::GetClientDataType() const
432 return GetLBox()->GetClientDataType();
435 void wxComboBox::SetClientDataType(wxClientDataType clientDataItemsType)
437 GetLBox()->SetClientDataType(clientDataItemsType);
440 int wxComboBox::DoInsertItems(const wxArrayStringsAdapter & items,
442 void **clientData, wxClientDataType type)
444 return GetLBox()->DoInsertItems(items, pos, clientData, type);
447 void wxComboBox::DoSetItemClientData(unsigned int n, void* clientData)
449 GetLBox()->DoSetItemClientData(n, clientData);
452 void *wxComboBox::DoGetItemClientData(unsigned int n) const
454 return GetLBox()->DoGetItemClientData(n);
457 bool wxComboBox::IsEditable() const
459 return GetTextCtrl() != NULL && (!HasFlag(wxCB_READONLY) || GetTextCtrl()->IsEditable() );
462 void wxComboBox::Undo()
465 if ( GetTextCtrl() ) GetTextCtrl()->Undo();
468 void wxComboBox::Redo()
471 if ( GetTextCtrl() ) GetTextCtrl()->Redo();
474 void wxComboBox::SelectAll()
476 if ( GetTextCtrl() ) GetTextCtrl()->SelectAll();
479 bool wxComboBox::CanCopy() const
481 if (GetTextCtrl() != NULL)
482 return GetTextCtrl()->CanCopy();
487 bool wxComboBox::CanCut() const
489 if (GetTextCtrl() != NULL)
490 return GetTextCtrl()->CanCut();
495 bool wxComboBox::CanPaste() const
498 return GetTextCtrl()->CanPaste();
503 bool wxComboBox::CanUndo() const
506 return GetTextCtrl()->CanUndo();
511 bool wxComboBox::CanRedo() const
514 return GetTextCtrl()->CanRedo();
520 // ----------------------------------------------------------------------------
521 // wxStdComboBoxInputHandler
522 // ----------------------------------------------------------------------------
524 wxStdComboBoxInputHandler::wxStdComboBoxInputHandler(wxInputHandler *inphand)
525 : wxStdInputHandler(inphand)
529 bool wxStdComboBoxInputHandler::HandleKey(wxInputConsumer *consumer,
530 const wxKeyEvent& event,
535 wxControlAction action;
536 switch ( event.GetKeyCode() )
539 action = wxACTION_COMBOBOX_POPUP;
543 action = wxACTION_COMBOBOX_DISMISS;
547 if ( !action.IsEmpty() )
549 consumer->PerformAction(action);
555 return wxStdInputHandler::HandleKey(consumer, event, pressed);
559 wxInputHandler *wxComboBox::GetStdInputHandler(wxInputHandler *handlerDef)
561 static wxStdComboBoxInputHandler s_handler(handlerDef);
566 #endif // wxUSE_COMBOBOX