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"
48 // ----------------------------------------------------------------------------
49 // wxComboListBox is a listbox modified to be used as a popup window in a
51 // ----------------------------------------------------------------------------
53 class wxComboListBox
: public wxListBox
, public wxComboPopup
58 virtual ~wxComboListBox();
60 // implement wxComboPopup methods
61 virtual bool Create(wxWindow
* parent
);
62 virtual void SetStringValue(const wxString
& s
);
63 virtual wxString
GetStringValue() const;
64 virtual wxWindow
*GetControl() { return this; }
65 virtual void OnPopup();
66 virtual wxSize
GetAdjustedSize(int minWidth
, int prefHeight
, int maxHeight
);
68 // fix virtual function hiding
69 virtual void SetSelection(int n
) { DoSetSelection(n
, true); }
70 void SetSelection(int n
, bool select
) { DoSetSelection(n
, select
); }
72 // used to process wxUniv actions
73 bool PerformAction(const wxControlAction
& action
,
75 const wxString
& strArg
);
78 // set m_clicked value from here
79 void OnLeftUp(wxMouseEvent
& event
);
85 // ----------------------------------------------------------------------------
86 // event tables and such
87 // ----------------------------------------------------------------------------
89 BEGIN_EVENT_TABLE(wxComboListBox
, wxListBox
)
90 EVT_LEFT_UP(wxComboListBox::OnLeftUp
)
93 IMPLEMENT_DYNAMIC_CLASS2(wxComboBox
, wxControl
, wxComboCtrl
)
95 // ============================================================================
97 // ============================================================================
99 // ----------------------------------------------------------------------------
101 // ----------------------------------------------------------------------------
103 wxComboListBox::wxComboListBox() : wxListBox(), wxComboPopup()
107 bool wxComboListBox::Create(wxWindow
* parent
)
109 if ( !wxListBox::Create(parent
, wxID_ANY
,
110 wxDefaultPosition
, wxDefaultSize
,
112 wxBORDER_SIMPLE
| wxLB_INT_HEIGHT
|
113 m_combo
->GetWindowStyle() & wxCB_SORT
? wxLB_SORT
: 0) )
116 // we don't react to the mouse events outside the window at all
122 wxComboListBox::~wxComboListBox()
126 wxString
wxComboListBox::GetStringValue() const
128 return wxListBox::GetStringSelection();
131 void wxComboListBox::SetStringValue(const wxString
& value
)
133 if ( !value
.empty() )
135 if (FindString(value
) != wxNOT_FOUND
)
136 wxListBox::SetStringSelection(value
);
139 wxListBox::SetSelection(-1);
142 void wxComboListBox::OnPopup()
146 bool wxComboListBox::PerformAction(const wxControlAction
& action
,
148 const wxString
& strArg
)
151 if ( action
== wxACTION_LISTBOX_FIND
)
153 // we don't let the listbox handle this as instead of just using the
154 // single key presses, as usual, we use the text ctrl value as prefix
155 // and this is done by wxComboCtrl itself
159 return wxListBox::PerformAction(action
, numArg
, strArg
);
162 void wxComboListBox::OnLeftUp(wxMouseEvent
& event
)
164 // we should dismiss the combo now
165 // first update the combo and close the listbox
167 m_combo
->SetValue(wxListBox::GetStringSelection());
169 // next let the user code have the event
170 wxCommandEvent
evt(wxEVT_COMMAND_COMBOBOX_SELECTED
,m_combo
->GetId());
171 evt
.SetInt(wxListBox::GetSelection());
172 evt
.SetEventObject(m_combo
);
173 m_combo
->ProcessEvent(evt
);
178 wxSize
wxComboListBox::GetAdjustedSize(int minWidth
,
179 int WXUNUSED(prefHeight
),
182 wxSize bestSize
= wxListBox::GetBestSize();
183 return wxSize(wxMax(bestSize
.x
,minWidth
),
184 wxMin(bestSize
.y
,maxHeight
));
187 // ----------------------------------------------------------------------------
189 // ----------------------------------------------------------------------------
191 void wxComboBox::Init()
193 m_lbox
= (wxListBox
*)NULL
;
196 wxComboBox::wxComboBox(wxWindow
*parent
,
198 const wxString
& value
,
201 const wxArrayString
& choices
,
203 const wxValidator
& validator
,
204 const wxString
& name
)
208 Create(parent
, id
, value
, pos
, size
, choices
, style
, validator
, name
);
211 bool wxComboBox::Create(wxWindow
*parent
,
213 const wxString
& value
,
216 const wxArrayString
& choices
,
218 const wxValidator
& validator
,
219 const wxString
& name
)
221 wxCArrayString
chs(choices
);
223 return Create(parent
, id
, value
, pos
, size
, chs
.GetCount(),
224 chs
.GetStrings(), style
, validator
, name
);
227 bool wxComboBox::Create(wxWindow
*parent
,
229 const wxString
& value
,
233 const wxString choices
[],
235 const wxValidator
& validator
,
236 const wxString
& name
)
238 if ( !wxComboCtrl::Create(parent
, id
, value
, pos
, size
, style
,
244 wxComboListBox
*combolbox
= new wxComboListBox();
245 SetPopupControl(combolbox
);
248 m_lbox
->Set(n
, choices
);
253 wxComboBox::~wxComboBox()
257 // ----------------------------------------------------------------------------
258 // wxComboBox methods forwarded to wxTextCtrl
259 // ----------------------------------------------------------------------------
261 wxString
wxComboBox::GetValue() const
263 return wxComboCtrl::GetValue();
266 void wxComboBox::SetValue(const wxString
& value
)
268 wxComboCtrl::SetValue(value
);
271 void wxComboBox::Copy()
273 if ( GetTextCtrl() ) GetTextCtrl()->Copy();
276 void wxComboBox::Cut()
278 if ( GetTextCtrl() ) GetTextCtrl()->Cut();
281 void wxComboBox::Paste()
283 if ( GetTextCtrl() ) GetTextCtrl()->Paste();
286 void wxComboBox::SetInsertionPoint(long pos
)
288 if ( GetTextCtrl() ) GetTextCtrl()->SetInsertionPoint(pos
);
291 void wxComboBox::SetInsertionPointEnd()
293 if ( GetTextCtrl() ) GetTextCtrl()->SetInsertionPointEnd();
296 long wxComboBox::GetInsertionPoint() const
299 return GetTextCtrl()->GetInsertionPoint();
303 wxTextPos
wxComboBox::GetLastPosition() const
306 return GetTextCtrl()->GetLastPosition();
310 void wxComboBox::Replace(long from
, long to
, const wxString
& value
)
312 if ( GetTextCtrl() ) GetTextCtrl()->Replace(from
, to
, value
);
315 void wxComboBox::Remove(long from
, long to
)
317 if ( GetTextCtrl() ) GetTextCtrl()->Remove(from
, to
);
320 void wxComboBox::SetSelection(long from
, long to
)
322 if ( GetTextCtrl() ) GetTextCtrl()->SetSelection(from
, to
);
325 void wxComboBox::SetEditable(bool editable
)
327 if ( GetTextCtrl() ) GetTextCtrl()->SetEditable(editable
);
330 // ----------------------------------------------------------------------------
331 // wxComboBox methods forwarded to wxListBox
332 // ----------------------------------------------------------------------------
334 void wxComboBox::Clear()
337 if ( GetTextCtrl() ) GetTextCtrl()->SetValue(wxEmptyString
);
340 void wxComboBox::Delete(unsigned int n
)
342 wxCHECK_RET( IsValid(n
), _T("invalid index in wxComboBox::Delete") );
344 if (GetSelection() == (int)n
)
345 if ( GetTextCtrl() ) GetTextCtrl()->SetValue(wxEmptyString
);
347 GetLBox()->Delete(n
);
350 unsigned int wxComboBox::GetCount() const
352 return GetLBox()->GetCount();
355 wxString
wxComboBox::GetString(unsigned int n
) const
357 wxCHECK_MSG( IsValid(n
), wxEmptyString
, _T("invalid index in wxComboBox::GetString") );
359 return GetLBox()->GetString(n
);
362 void wxComboBox::SetString(unsigned int n
, const wxString
& s
)
364 wxCHECK_RET( IsValid(n
), _T("invalid index in wxComboBox::SetString") );
366 GetLBox()->SetString(n
, s
);
369 int wxComboBox::FindString(const wxString
& s
, bool bCase
) const
371 return GetLBox()->FindString(s
, bCase
);
374 void wxComboBox::SetSelection(int n
)
376 wxCHECK_RET( IsValid(n
), _T("invalid index in wxComboBox::Select") );
378 GetLBox()->SetSelection(n
);
379 if ( GetTextCtrl() ) GetTextCtrl()->SetValue(GetLBox()->GetString(n
));
382 int wxComboBox::GetSelection() const
384 #if 1 // FIXME:: What is the correct behavior?
385 // if the current value isn't one of the listbox strings, return -1
386 return GetLBox()->GetSelection();
388 // Why oh why is this done this way?
389 // It is not because the value displayed in the text can be found
390 // in the list that it is the item that is selected!
391 return FindString(if ( GetTextCtrl() ) GetTextCtrl()->GetValue());
395 int wxComboBox::DoAppend(const wxString
& item
)
397 return GetLBox()->Append(item
);
400 int wxComboBox::DoInsert(const wxString
& item
, unsigned int pos
)
402 wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT
), -1, wxT("can't insert into sorted list"));
403 wxCHECK_MSG(IsValidInsert(pos
), -1, wxT("invalid index"));
405 if (pos
== GetCount())
406 return DoAppend(item
);
408 GetLBox()->Insert(item
, pos
);
412 void wxComboBox::DoSetItemClientData(unsigned int n
, void* clientData
)
414 GetLBox()->SetClientData(n
, clientData
);
417 void *wxComboBox::DoGetItemClientData(unsigned int n
) const
419 return GetLBox()->GetClientData(n
);
422 void wxComboBox::DoSetItemClientObject(unsigned int n
, wxClientData
* clientData
)
424 GetLBox()->SetClientObject(n
, clientData
);
427 wxClientData
* wxComboBox::DoGetItemClientObject(unsigned int n
) const
429 return GetLBox()->GetClientObject(n
);
432 bool wxComboBox::IsEditable() const
434 return GetTextCtrl() != NULL
&& (!HasFlag(wxCB_READONLY
) || GetTextCtrl()->IsEditable() );
437 void wxComboBox::Undo()
440 if ( GetTextCtrl() ) GetTextCtrl()->Undo();
443 void wxComboBox::Redo()
446 if ( GetTextCtrl() ) GetTextCtrl()->Redo();
449 void wxComboBox::SelectAll()
451 if ( GetTextCtrl() ) GetTextCtrl()->SelectAll();
454 bool wxComboBox::CanCopy() const
456 if (GetTextCtrl() != NULL
)
457 return GetTextCtrl()->CanCopy();
462 bool wxComboBox::CanCut() const
464 if (GetTextCtrl() != NULL
)
465 return GetTextCtrl()->CanCut();
470 bool wxComboBox::CanPaste() const
473 return GetTextCtrl()->CanPaste();
478 bool wxComboBox::CanUndo() const
481 return GetTextCtrl()->CanUndo();
486 bool wxComboBox::CanRedo() const
489 return GetTextCtrl()->CanRedo();
495 // ----------------------------------------------------------------------------
496 // wxStdComboBoxInputHandler
497 // ----------------------------------------------------------------------------
499 wxStdComboBoxInputHandler::wxStdComboBoxInputHandler(wxInputHandler
*inphand
)
500 : wxStdInputHandler(inphand
)
504 bool wxStdComboBoxInputHandler::HandleKey(wxInputConsumer
*consumer
,
505 const wxKeyEvent
& event
,
510 wxControlAction action
;
511 switch ( event
.GetKeyCode() )
514 action
= wxACTION_COMBOBOX_POPUP
;
518 action
= wxACTION_COMBOBOX_DISMISS
;
522 if ( !action
.IsEmpty() )
524 consumer
->PerformAction(action
);
530 return wxStdInputHandler::HandleKey(consumer
, event
, pressed
);
534 #endif // wxUSE_COMBOBOX