1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/univ/combobox.cpp
3 // Purpose: wxComboBox implementation
4 // Author: Vadim Zeitlin
7 // Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 #include "wx/wxprec.h"
30 #include "wx/button.h"
31 #include "wx/combobox.h"
32 #include "wx/listbox.h"
33 #include "wx/textctrl.h"
34 #include "wx/bmpbuttn.h"
36 #include "wx/validate.h"
39 #include "wx/tooltip.h"
42 #include "wx/univ/renderer.h"
43 #include "wx/univ/inphand.h"
44 #include "wx/univ/theme.h"
46 // ----------------------------------------------------------------------------
47 // wxStdComboBoxInputHandler: allows the user to open/close the combo from kbd
48 // ----------------------------------------------------------------------------
50 class WXDLLEXPORT wxStdComboBoxInputHandler
: public wxStdInputHandler
53 wxStdComboBoxInputHandler(wxInputHandler
*inphand
);
55 virtual bool HandleKey(wxInputConsumer
*consumer
,
56 const wxKeyEvent
& event
,
60 // ----------------------------------------------------------------------------
61 // wxComboListBox is a listbox modified to be used as a popup window in a
63 // ----------------------------------------------------------------------------
65 class wxComboListBox
: public wxListBox
, public wxComboPopup
70 virtual ~wxComboListBox();
72 // implement wxComboPopup methods
73 virtual bool Create(wxWindow
* parent
);
74 virtual void SetStringValue(const wxString
& s
);
75 virtual wxString
GetStringValue() const;
76 virtual wxWindow
*GetControl() { return this; }
77 virtual void OnPopup();
78 virtual wxSize
GetAdjustedSize(int minWidth
, int prefHeight
, int maxHeight
);
80 // fix virtual function hiding
81 virtual void SetSelection(int n
) { DoSetSelection(n
, true); }
82 void SetSelection(int n
, bool select
) { DoSetSelection(n
, select
); }
84 // used to process wxUniv actions
85 bool PerformAction(const wxControlAction
& action
,
87 const wxString
& strArg
);
90 // set m_clicked value from here
91 void OnLeftUp(wxMouseEvent
& event
);
94 friend class wxComboBox
; // it accesses our DoGetItemClientData()
99 // ----------------------------------------------------------------------------
100 // event tables and such
101 // ----------------------------------------------------------------------------
103 BEGIN_EVENT_TABLE(wxComboListBox
, wxListBox
)
104 EVT_LEFT_UP(wxComboListBox::OnLeftUp
)
107 // ============================================================================
109 // ============================================================================
111 // ----------------------------------------------------------------------------
113 // ----------------------------------------------------------------------------
115 wxComboListBox::wxComboListBox() : wxListBox(), wxComboPopup()
119 bool wxComboListBox::Create(wxWindow
* parent
)
121 if ( !wxListBox::Create(parent
, wxID_ANY
,
122 wxDefaultPosition
, wxDefaultSize
,
125 ( m_combo
->GetWindowStyle() & wxCB_SORT
? wxLB_SORT
: 0 ) ) )
128 // we don't react to the mouse events outside the window at all
134 wxComboListBox::~wxComboListBox()
138 wxString
wxComboListBox::GetStringValue() const
140 return wxListBox::GetStringSelection();
143 void wxComboListBox::SetStringValue(const wxString
& value
)
145 if ( !value
.empty() )
147 if (FindString(value
) != wxNOT_FOUND
)
148 wxListBox::SetStringSelection(value
);
151 wxListBox::SetSelection(-1);
154 void wxComboListBox::OnPopup()
158 bool wxComboListBox::PerformAction(const wxControlAction
& action
,
160 const wxString
& strArg
)
163 if ( action
== wxACTION_LISTBOX_FIND
)
165 // we don't let the listbox handle this as instead of just using the
166 // single key presses, as usual, we use the text ctrl value as prefix
167 // and this is done by wxComboCtrl itself
171 return wxListBox::PerformAction(action
, numArg
, strArg
);
174 void wxComboListBox::OnLeftUp(wxMouseEvent
& event
)
176 // we should dismiss the combo now
177 // first update the combo and close the listbox
179 m_combo
->SetValue(wxListBox::GetStringSelection());
181 // next let the user code have the event
182 wxCommandEvent
evt(wxEVT_COMBOBOX
,m_combo
->GetId());
183 evt
.SetInt(wxListBox::GetSelection());
184 evt
.SetEventObject(m_combo
);
185 m_combo
->ProcessWindowEvent(evt
);
190 wxSize
wxComboListBox::GetAdjustedSize(int minWidth
,
191 int WXUNUSED(prefHeight
),
194 wxSize bestSize
= wxListBox::GetBestSize();
195 return wxSize(wxMax(bestSize
.x
,minWidth
),
196 wxMin(bestSize
.y
,maxHeight
));
199 // ----------------------------------------------------------------------------
201 // ----------------------------------------------------------------------------
203 void wxComboBox::Init()
208 wxComboBox::wxComboBox(wxWindow
*parent
,
210 const wxString
& value
,
213 const wxArrayString
& choices
,
215 const wxValidator
& validator
,
216 const wxString
& name
)
220 Create(parent
, id
, value
, pos
, size
, choices
, style
, validator
, name
);
223 bool wxComboBox::Create(wxWindow
*parent
,
225 const wxString
& value
,
228 const wxArrayString
& choices
,
230 const wxValidator
& validator
,
231 const wxString
& name
)
233 wxCArrayString
chs(choices
);
235 return Create(parent
, id
, value
, pos
, size
, chs
.GetCount(),
236 chs
.GetStrings(), style
, validator
, name
);
239 bool wxComboBox::Create(wxWindow
*parent
,
241 const wxString
& value
,
245 const wxString choices
[],
247 const wxValidator
& validator
,
248 const wxString
& name
)
250 if ( !wxComboCtrl::Create(parent
, id
, value
, pos
, size
, style
,
256 wxComboListBox
*combolbox
= new wxComboListBox();
257 SetPopupControl(combolbox
);
260 m_lbox
->Set(n
, choices
);
265 wxComboBox::~wxComboBox()
269 // ----------------------------------------------------------------------------
270 // wxComboBox methods forwarded to wxTextCtrl
271 // ----------------------------------------------------------------------------
273 wxString
wxComboBox::DoGetValue() const
275 return GetTextCtrl() ? GetTextCtrl()->GetValue() : m_valueString
;
278 void wxComboBox::SetValue(const wxString
& value
)
281 GetTextCtrl()->SetValue(value
);
283 m_valueString
= 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 SetValue(wxEmptyString
);
365 void wxComboBox::DoDeleteOneItem(unsigned int n
)
367 wxCHECK_RET( IsValid(n
), wxT("invalid index in wxComboBox::Delete") );
369 if (GetSelection() == (int)n
)
370 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
, wxT("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
), wxT("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
)), wxT("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 behaviour?
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