]> git.saurik.com Git - wxWidgets.git/blame - src/univ/combobox.cpp
Missing #includes to allow wx/mac/carbon/tooltip.h be included first by user.
[wxWidgets.git] / src / univ / combobox.cpp
CommitLineData
1e6feb95 1/////////////////////////////////////////////////////////////////////////////
11e62fe6 2// Name: src/univ/combobox.cpp
6d0ce565 3// Purpose: wxComboBox implementation
1e6feb95
VZ
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 15.12.00
7// RCS-ID: $Id$
442b35b5 8// Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
65571936 9// Licence: wxWindows licence
1e6feb95
VZ
10/////////////////////////////////////////////////////////////////////////////
11
1e6feb95
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
1e6feb95
VZ
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
26#if wxUSE_COMBOBOX
27
28#ifndef WX_PRECOMP
29 #include "wx/log.h"
30
31 #include "wx/button.h"
32 #include "wx/combobox.h"
33 #include "wx/listbox.h"
34 #include "wx/textctrl.h"
8cb172b4 35 #include "wx/bmpbuttn.h"
1e6feb95
VZ
36
37 #include "wx/validate.h"
38#endif
39
d4e5272b 40#include "wx/tooltip.h"
a340b80d 41#include "wx/combo.h"
1e6feb95
VZ
42
43#include "wx/univ/renderer.h"
44#include "wx/univ/inphand.h"
45#include "wx/univ/theme.h"
46
1e6feb95
VZ
47
48// ----------------------------------------------------------------------------
49// wxComboListBox is a listbox modified to be used as a popup window in a
50// combobox
51// ----------------------------------------------------------------------------
52
53class wxComboListBox : public wxListBox, public wxComboPopup
54{
55public:
56 // ctor and dtor
e051d008 57 wxComboListBox();
1e6feb95
VZ
58 virtual ~wxComboListBox();
59
60 // implement wxComboPopup methods
a340b80d
VZ
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);
1e6feb95 67
d2fde247
VZ
68 // fix virtual function hiding
69 virtual void SetSelection(int n) { DoSetSelection(n, true); }
70 void SetSelection(int n, bool select) { DoSetSelection(n, select); }
71
6f02a879
VZ
72 // used to process wxUniv actions
73 bool PerformAction(const wxControlAction& action,
74 long numArg,
75 const wxString& strArg);
76
1e6feb95 77protected:
55f095d4
VZ
78 // set m_clicked value from here
79 void OnLeftUp(wxMouseEvent& event);
80
1e6feb95 81private:
1e6feb95
VZ
82 DECLARE_EVENT_TABLE()
83};
84
85// ----------------------------------------------------------------------------
86// event tables and such
87// ----------------------------------------------------------------------------
88
1e6feb95 89BEGIN_EVENT_TABLE(wxComboListBox, wxListBox)
55f095d4 90 EVT_LEFT_UP(wxComboListBox::OnLeftUp)
1e6feb95
VZ
91END_EVENT_TABLE()
92
a57d600f 93IMPLEMENT_DYNAMIC_CLASS2(wxComboBox, wxControl, wxComboCtrl)
1e6feb95
VZ
94
95// ============================================================================
96// implementation
97// ============================================================================
98
99// ----------------------------------------------------------------------------
a340b80d 100// wxComboListBox
1e6feb95
VZ
101// ----------------------------------------------------------------------------
102
e051d008 103wxComboListBox::wxComboListBox() : wxListBox(), wxComboPopup()
1e6feb95 104{
1e6feb95
VZ
105}
106
a340b80d 107bool wxComboListBox::Create(wxWindow* parent)
1e6feb95 108{
a340b80d
VZ
109 if ( !wxListBox::Create(parent, wxID_ANY,
110 wxDefaultPosition, wxDefaultSize,
111 0, NULL,
112 wxBORDER_SIMPLE | wxLB_INT_HEIGHT |
113 m_combo->GetWindowStyle() & wxCB_SORT ? wxLB_SORT : 0) )
a290fa5a 114 return false;
1e6feb95 115
a340b80d
VZ
116 // we don't react to the mouse events outside the window at all
117 StopAutoScrolling();
1e6feb95 118
a290fa5a 119 return true;
1e6feb95
VZ
120}
121
a340b80d 122wxComboListBox::~wxComboListBox()
1e6feb95 123{
1e6feb95
VZ
124}
125
a340b80d 126wxString wxComboListBox::GetStringValue() const
1e6feb95 127{
a340b80d 128 return wxListBox::GetStringSelection();
1e6feb95
VZ
129}
130
a340b80d 131void wxComboListBox::SetStringValue(const wxString& value)
1e6feb95 132{
a340b80d
VZ
133 if ( !value.empty() )
134 wxListBox::SetStringSelection(value);
135 else
136 wxListBox::SetSelection(-1);
1e6feb95
VZ
137}
138
a340b80d 139void wxComboListBox::OnPopup()
1e6feb95
VZ
140{
141}
142
143bool wxComboListBox::PerformAction(const wxControlAction& action,
144 long numArg,
145 const wxString& strArg)
146
147{
148 if ( action == wxACTION_LISTBOX_FIND )
149 {
150 // we don't let the listbox handle this as instead of just using the
151 // single key presses, as usual, we use the text ctrl value as prefix
a57d600f 152 // and this is done by wxComboCtrl itself
a290fa5a 153 return true;
1e6feb95
VZ
154 }
155
156 return wxListBox::PerformAction(action, numArg, strArg);
157}
158
55f095d4
VZ
159void wxComboListBox::OnLeftUp(wxMouseEvent& event)
160{
161 // we should dismiss the combo now
a340b80d
VZ
162 // first update the combo and close the listbox
163 Dismiss();
164 m_combo->SetValue(wxListBox::GetStringSelection());
55f095d4 165
a340b80d
VZ
166 // next let the user code have the event
167 wxCommandEvent evt(wxEVT_COMMAND_COMBOBOX_SELECTED,m_combo->GetId());
168 evt.SetInt(wxListBox::GetSelection());
169 evt.SetEventObject(m_combo);
170 m_combo->ProcessEvent(evt);
55f095d4 171
a340b80d 172 event.Skip();
e2ca829e
JS
173}
174
a340b80d
VZ
175wxSize wxComboListBox::GetAdjustedSize(int minWidth,
176 int WXUNUSED(prefHeight),
177 int maxHeight)
1e6feb95 178{
a340b80d
VZ
179 wxSize bestSize = wxListBox::GetBestSize();
180 return wxSize(wxMax(bestSize.x,minWidth),
181 wxMin(bestSize.y,maxHeight));
1e6feb95
VZ
182}
183
184// ----------------------------------------------------------------------------
185// wxComboBox
186// ----------------------------------------------------------------------------
187
188void wxComboBox::Init()
189{
190 m_lbox = (wxListBox *)NULL;
191}
192
584ad2a3
MB
193wxComboBox::wxComboBox(wxWindow *parent,
194 wxWindowID id,
195 const wxString& value,
196 const wxPoint& pos,
197 const wxSize& size,
198 const wxArrayString& choices,
199 long style,
200 const wxValidator& validator,
201 const wxString& name)
202{
203 Init();
204
205 Create(parent, id, value, pos, size, choices, style, validator, name);
206}
207
208bool wxComboBox::Create(wxWindow *parent,
209 wxWindowID id,
210 const wxString& value,
211 const wxPoint& pos,
212 const wxSize& size,
213 const wxArrayString& choices,
214 long style,
215 const wxValidator& validator,
216 const wxString& name)
217{
218 wxCArrayString chs(choices);
219
220 return Create(parent, id, value, pos, size, chs.GetCount(),
221 chs.GetStrings(), style, validator, name);
222}
223
1e6feb95
VZ
224bool wxComboBox::Create(wxWindow *parent,
225 wxWindowID id,
226 const wxString& value,
227 const wxPoint& pos,
228 const wxSize& size,
229 int n,
ba1e9d6c 230 const wxString choices[],
1e6feb95
VZ
231 long style,
232 const wxValidator& validator,
233 const wxString& name)
234{
a57d600f 235 if ( !wxComboCtrl::Create(parent, id, value, pos, size, style,
1e6feb95
VZ
236 validator, name) )
237 {
a290fa5a 238 return false;
1e6feb95
VZ
239 }
240
e051d008 241 wxComboListBox *combolbox = new wxComboListBox();
a340b80d
VZ
242 SetPopupControl(combolbox);
243
1e6feb95
VZ
244 m_lbox = combolbox;
245 m_lbox->Set(n, choices);
246
a290fa5a 247 return true;
1e6feb95
VZ
248}
249
250wxComboBox::~wxComboBox()
251{
252}
253
254// ----------------------------------------------------------------------------
255// wxComboBox methods forwarded to wxTextCtrl
256// ----------------------------------------------------------------------------
257
258wxString wxComboBox::GetValue() const
259{
a57d600f 260 return wxComboCtrl::GetValue();
1e6feb95
VZ
261}
262
263void wxComboBox::SetValue(const wxString& value)
264{
a57d600f 265 wxComboCtrl::SetValue(value);
1e6feb95
VZ
266}
267
268void wxComboBox::Copy()
269{
a340b80d 270 if ( GetTextCtrl() ) GetTextCtrl()->Copy();
1e6feb95
VZ
271}
272
273void wxComboBox::Cut()
274{
a340b80d 275 if ( GetTextCtrl() ) GetTextCtrl()->Cut();
1e6feb95
VZ
276}
277
278void wxComboBox::Paste()
279{
a340b80d 280 if ( GetTextCtrl() ) GetTextCtrl()->Paste();
1e6feb95
VZ
281}
282
283void wxComboBox::SetInsertionPoint(long pos)
284{
a340b80d 285 if ( GetTextCtrl() ) GetTextCtrl()->SetInsertionPoint(pos);
1e6feb95
VZ
286}
287
288void wxComboBox::SetInsertionPointEnd()
289{
a340b80d 290 if ( GetTextCtrl() ) GetTextCtrl()->SetInsertionPointEnd();
1e6feb95
VZ
291}
292
293long wxComboBox::GetInsertionPoint() const
294{
a340b80d
VZ
295 if ( GetTextCtrl() )
296 return GetTextCtrl()->GetInsertionPoint();
297 return -1;
1e6feb95
VZ
298}
299
7d8268a1 300wxTextPos wxComboBox::GetLastPosition() const
1e6feb95 301{
a340b80d
VZ
302 if ( GetTextCtrl() )
303 return GetTextCtrl()->GetLastPosition();
304 return -1;
1e6feb95
VZ
305}
306
307void wxComboBox::Replace(long from, long to, const wxString& value)
308{
a340b80d 309 if ( GetTextCtrl() ) GetTextCtrl()->Replace(from, to, value);
1e6feb95
VZ
310}
311
312void wxComboBox::Remove(long from, long to)
313{
a340b80d 314 if ( GetTextCtrl() ) GetTextCtrl()->Remove(from, to);
1e6feb95
VZ
315}
316
317void wxComboBox::SetSelection(long from, long to)
318{
a340b80d 319 if ( GetTextCtrl() ) GetTextCtrl()->SetSelection(from, to);
1e6feb95
VZ
320}
321
322void wxComboBox::SetEditable(bool editable)
323{
a340b80d 324 if ( GetTextCtrl() ) GetTextCtrl()->SetEditable(editable);
1e6feb95
VZ
325}
326
327// ----------------------------------------------------------------------------
328// wxComboBox methods forwarded to wxListBox
329// ----------------------------------------------------------------------------
330
331void wxComboBox::Clear()
332{
333 GetLBox()->Clear();
a340b80d 334 if ( GetTextCtrl() ) GetTextCtrl()->SetValue(wxEmptyString);
1e6feb95
VZ
335}
336
aa61d352 337void wxComboBox::Delete(unsigned int n)
1e6feb95 338{
8228b893 339 wxCHECK_RET( IsValid(n), _T("invalid index in wxComboBox::Delete") );
48aa18c0 340
aa61d352 341 if (GetSelection() == (int)n)
a340b80d 342 if ( GetTextCtrl() ) GetTextCtrl()->SetValue(wxEmptyString);
48aa18c0 343
1e6feb95
VZ
344 GetLBox()->Delete(n);
345}
346
aa61d352 347unsigned int wxComboBox::GetCount() const
1e6feb95
VZ
348{
349 return GetLBox()->GetCount();
350}
351
aa61d352 352wxString wxComboBox::GetString(unsigned int n) const
1e6feb95 353{
8228b893 354 wxCHECK_MSG( IsValid(n), wxEmptyString, _T("invalid index in wxComboBox::GetString") );
48aa18c0 355
1e6feb95
VZ
356 return GetLBox()->GetString(n);
357}
358
aa61d352 359void wxComboBox::SetString(unsigned int n, const wxString& s)
1e6feb95 360{
8228b893 361 wxCHECK_RET( IsValid(n), _T("invalid index in wxComboBox::SetString") );
48aa18c0 362
1e6feb95
VZ
363 GetLBox()->SetString(n, s);
364}
365
11e62fe6 366int wxComboBox::FindString(const wxString& s, bool bCase) const
1e6feb95 367{
11e62fe6 368 return GetLBox()->FindString(s, bCase);
1e6feb95
VZ
369}
370
c6179a84 371void wxComboBox::SetSelection(int n)
1e6feb95 372{
8228b893 373 wxCHECK_RET( IsValid(n), _T("invalid index in wxComboBox::Select") );
1e6feb95
VZ
374
375 GetLBox()->SetSelection(n);
a340b80d 376 if ( GetTextCtrl() ) GetTextCtrl()->SetValue(GetLBox()->GetString(n));
1e6feb95
VZ
377}
378
379int wxComboBox::GetSelection() const
380{
48aa18c0 381#if 1 // FIXME:: What is the correct behavior?
1e6feb95 382 // if the current value isn't one of the listbox strings, return -1
48aa18c0 383 return GetLBox()->GetSelection();
150e31d2
JS
384#else
385 // Why oh why is this done this way?
386 // It is not because the value displayed in the text can be found
48aa18c0 387 // in the list that it is the item that is selected!
a340b80d 388 return FindString(if ( GetTextCtrl() ) GetTextCtrl()->GetValue());
48aa18c0 389#endif
1e6feb95
VZ
390}
391
392int wxComboBox::DoAppend(const wxString& item)
393{
394 return GetLBox()->Append(item);
395}
396
aa61d352 397int wxComboBox::DoInsert(const wxString& item, unsigned int pos)
243dbf1a
VZ
398{
399 wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT), -1, wxT("can't insert into sorted list"));
8228b893 400 wxCHECK_MSG(IsValidInsert(pos), -1, wxT("invalid index"));
243dbf1a 401
aa61d352 402 if (pos == GetCount())
243dbf1a
VZ
403 return DoAppend(item);
404
3f85391e 405 GetLBox()->Insert(item, pos);
243dbf1a
VZ
406 return pos;
407}
408
aa61d352 409void wxComboBox::DoSetItemClientData(unsigned int n, void* clientData)
1e6feb95
VZ
410{
411 GetLBox()->SetClientData(n, clientData);
412}
413
aa61d352 414void *wxComboBox::DoGetItemClientData(unsigned int n) const
1e6feb95
VZ
415{
416 return GetLBox()->GetClientData(n);
417}
418
aa61d352 419void wxComboBox::DoSetItemClientObject(unsigned int n, wxClientData* clientData)
1e6feb95
VZ
420{
421 GetLBox()->SetClientObject(n, clientData);
422}
423
aa61d352 424wxClientData* wxComboBox::DoGetItemClientObject(unsigned int n) const
1e6feb95
VZ
425{
426 return GetLBox()->GetClientObject(n);
427}
428
150e31d2
JS
429bool wxComboBox::IsEditable() const
430{
a340b80d 431 return GetTextCtrl() != NULL && (!HasFlag(wxCB_READONLY) || GetTextCtrl()->IsEditable() );
150e31d2
JS
432}
433
434void wxComboBox::Undo()
435{
436 if (IsEditable())
a340b80d 437 if ( GetTextCtrl() ) GetTextCtrl()->Undo();
150e31d2
JS
438}
439
440void wxComboBox::Redo()
441{
442 if (IsEditable())
a340b80d 443 if ( GetTextCtrl() ) GetTextCtrl()->Redo();
150e31d2
JS
444}
445
446void wxComboBox::SelectAll()
447{
a340b80d 448 if ( GetTextCtrl() ) GetTextCtrl()->SelectAll();
150e31d2
JS
449}
450
451bool wxComboBox::CanCopy() const
452{
a340b80d
VZ
453 if (GetTextCtrl() != NULL)
454 return GetTextCtrl()->CanCopy();
150e31d2
JS
455 else
456 return false;
457}
458
459bool wxComboBox::CanCut() const
460{
a340b80d
VZ
461 if (GetTextCtrl() != NULL)
462 return GetTextCtrl()->CanCut();
150e31d2
JS
463 else
464 return false;
465}
466
467bool wxComboBox::CanPaste() const
468{
469 if (IsEditable())
a340b80d 470 return GetTextCtrl()->CanPaste();
150e31d2
JS
471 else
472 return false;
473}
474
475bool wxComboBox::CanUndo() const
476{
477 if (IsEditable())
a340b80d 478 return GetTextCtrl()->CanUndo();
150e31d2
JS
479 else
480 return false;
481}
482
483bool wxComboBox::CanRedo() const
484{
485 if (IsEditable())
a340b80d 486 return GetTextCtrl()->CanRedo();
150e31d2
JS
487 else
488 return false;
489}
490
491
1e6feb95
VZ
492// ----------------------------------------------------------------------------
493// wxStdComboBoxInputHandler
494// ----------------------------------------------------------------------------
495
496wxStdComboBoxInputHandler::wxStdComboBoxInputHandler(wxInputHandler *inphand)
497 : wxStdInputHandler(inphand)
498{
499}
500
23645bfa 501bool wxStdComboBoxInputHandler::HandleKey(wxInputConsumer *consumer,
1e6feb95
VZ
502 const wxKeyEvent& event,
503 bool pressed)
504{
505 if ( pressed )
506 {
507 wxControlAction action;
508 switch ( event.GetKeyCode() )
509 {
510 case WXK_DOWN:
511 action = wxACTION_COMBOBOX_POPUP;
512 break;
513
514 case WXK_ESCAPE:
515 action = wxACTION_COMBOBOX_DISMISS;
516 break;
517 }
518
a290fa5a 519 if ( !action.IsEmpty() )
1e6feb95 520 {
23645bfa 521 consumer->PerformAction(action);
1e6feb95 522
a290fa5a 523 return true;
1e6feb95
VZ
524 }
525 }
526
23645bfa 527 return wxStdInputHandler::HandleKey(consumer, event, pressed);
1e6feb95
VZ
528}
529
a340b80d 530
1e6feb95 531#endif // wxUSE_COMBOBOX