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_COMMAND_COMBOBOX_SELECTED
,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 wxComboCtrl::GetValue();
279 void wxComboBox::SetValue(const wxString
& value
)
281 wxComboCtrl::SetValue(value
);
284 void wxComboBox::WriteText(const wxString
& value
)
286 if ( GetTextCtrl() ) GetTextCtrl()->WriteText(value
);
289 void wxComboBox::Copy()
291 if ( GetTextCtrl() ) GetTextCtrl()->Copy();
294 void wxComboBox::Cut()
296 if ( GetTextCtrl() ) GetTextCtrl()->Cut();
299 void wxComboBox::Paste()
301 if ( GetTextCtrl() ) GetTextCtrl()->Paste();
304 void wxComboBox::SetInsertionPoint(long pos
)
306 if ( GetTextCtrl() ) GetTextCtrl()->SetInsertionPoint(pos
);
309 void wxComboBox::SetInsertionPointEnd()
311 if ( GetTextCtrl() ) GetTextCtrl()->SetInsertionPointEnd();
314 long wxComboBox::GetInsertionPoint() const
317 return GetTextCtrl()->GetInsertionPoint();
321 wxTextPos
wxComboBox::GetLastPosition() const
324 return GetTextCtrl()->GetLastPosition();
328 void wxComboBox::Replace(long from
, long to
, const wxString
& value
)
330 if ( GetTextCtrl() ) GetTextCtrl()->Replace(from
, to
, value
);
333 void wxComboBox::Remove(long from
, long to
)
335 if ( GetTextCtrl() ) GetTextCtrl()->Remove(from
, to
);
338 void wxComboBox::SetSelection(long from
, long to
)
340 if ( GetTextCtrl() ) GetTextCtrl()->SetSelection(from
, to
);
343 void wxComboBox::GetSelection(long *from
, long *to
) const
345 if ( GetTextCtrl() ) GetTextCtrl()->GetSelection(from
, to
);
348 void wxComboBox::SetEditable(bool editable
)
350 if ( GetTextCtrl() ) GetTextCtrl()->SetEditable(editable
);
353 // ----------------------------------------------------------------------------
354 // wxComboBox methods forwarded to wxListBox
355 // ----------------------------------------------------------------------------
357 void wxComboBox::DoClear()
360 if ( GetTextCtrl() ) GetTextCtrl()->SetValue(wxEmptyString
);
363 void wxComboBox::DoDeleteOneItem(unsigned int n
)
365 wxCHECK_RET( IsValid(n
), wxT("invalid index in wxComboBox::Delete") );
367 if (GetSelection() == (int)n
)
368 if ( GetTextCtrl() ) GetTextCtrl()->SetValue(wxEmptyString
);
370 GetLBox()->Delete(n
);
373 unsigned int wxComboBox::GetCount() const
375 return GetLBox()->GetCount();
378 wxString
wxComboBox::GetString(unsigned int n
) const
380 wxCHECK_MSG( IsValid(n
), wxEmptyString
, wxT("invalid index in wxComboBox::GetString") );
382 return GetLBox()->GetString(n
);
385 void wxComboBox::SetString(unsigned int n
, const wxString
& s
)
387 wxCHECK_RET( IsValid(n
), wxT("invalid index in wxComboBox::SetString") );
389 GetLBox()->SetString(n
, s
);
392 int wxComboBox::FindString(const wxString
& s
, bool bCase
) const
394 return GetLBox()->FindString(s
, bCase
);
397 void wxComboBox::SetSelection(int n
)
399 wxCHECK_RET( (n
== wxNOT_FOUND
|| IsValid(n
)), wxT("invalid index in wxComboBox::Select") );
401 GetLBox()->SetSelection(n
);
404 if ( n
!= wxNOT_FOUND
)
405 str
= GetLBox()->GetString(n
);
410 int wxComboBox::GetSelection() const
412 #if 1 // FIXME:: What is the correct behaviour?
413 // if the current value isn't one of the listbox strings, return -1
414 return GetLBox()->GetSelection();
416 // Why oh why is this done this way?
417 // It is not because the value displayed in the text can be found
418 // in the list that it is the item that is selected!
419 return FindString(if ( GetTextCtrl() ) GetTextCtrl()->GetValue());
423 wxString
wxComboBox::GetStringSelection() const
425 return GetLBox()->GetStringSelection();
428 wxClientDataType
wxComboBox::GetClientDataType() const
430 return GetLBox()->GetClientDataType();
433 void wxComboBox::SetClientDataType(wxClientDataType clientDataItemsType
)
435 GetLBox()->SetClientDataType(clientDataItemsType
);
438 int wxComboBox::DoInsertItems(const wxArrayStringsAdapter
& items
,
440 void **clientData
, wxClientDataType type
)
442 return GetLBox()->DoInsertItems(items
, pos
, clientData
, type
);
445 void wxComboBox::DoSetItemClientData(unsigned int n
, void* clientData
)
447 GetLBox()->DoSetItemClientData(n
, clientData
);
450 void *wxComboBox::DoGetItemClientData(unsigned int n
) const
452 return GetLBox()->DoGetItemClientData(n
);
455 bool wxComboBox::IsEditable() const
457 return GetTextCtrl() != NULL
&& (!HasFlag(wxCB_READONLY
) || GetTextCtrl()->IsEditable() );
460 void wxComboBox::Undo()
463 if ( GetTextCtrl() ) GetTextCtrl()->Undo();
466 void wxComboBox::Redo()
469 if ( GetTextCtrl() ) GetTextCtrl()->Redo();
472 void wxComboBox::SelectAll()
474 if ( GetTextCtrl() ) GetTextCtrl()->SelectAll();
477 bool wxComboBox::CanCopy() const
479 if (GetTextCtrl() != NULL
)
480 return GetTextCtrl()->CanCopy();
485 bool wxComboBox::CanCut() const
487 if (GetTextCtrl() != NULL
)
488 return GetTextCtrl()->CanCut();
493 bool wxComboBox::CanPaste() const
496 return GetTextCtrl()->CanPaste();
501 bool wxComboBox::CanUndo() const
504 return GetTextCtrl()->CanUndo();
509 bool wxComboBox::CanRedo() const
512 return GetTextCtrl()->CanRedo();
518 // ----------------------------------------------------------------------------
519 // wxStdComboBoxInputHandler
520 // ----------------------------------------------------------------------------
522 wxStdComboBoxInputHandler::wxStdComboBoxInputHandler(wxInputHandler
*inphand
)
523 : wxStdInputHandler(inphand
)
527 bool wxStdComboBoxInputHandler::HandleKey(wxInputConsumer
*consumer
,
528 const wxKeyEvent
& event
,
533 wxControlAction action
;
534 switch ( event
.GetKeyCode() )
537 action
= wxACTION_COMBOBOX_POPUP
;
541 action
= wxACTION_COMBOBOX_DISMISS
;
545 if ( !action
.IsEmpty() )
547 consumer
->PerformAction(action
);
553 return wxStdInputHandler::HandleKey(consumer
, event
, pressed
);
557 wxInputHandler
*wxComboBox::GetStdInputHandler(wxInputHandler
*handlerDef
)
559 static wxStdComboBoxInputHandler
s_handler(handlerDef
);
564 #endif // wxUSE_COMBOBOX