]> git.saurik.com Git - wxWidgets.git/blame - src/univ/combobox.cpp
Check for invalid items in generic wxDataViewCtrl::GetSelections().
[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
9467bdb7
VZ
47// ----------------------------------------------------------------------------
48// wxStdComboBoxInputHandler: allows the user to open/close the combo from kbd
49// ----------------------------------------------------------------------------
50
51class WXDLLEXPORT wxStdComboBoxInputHandler : public wxStdInputHandler
52{
53public:
54 wxStdComboBoxInputHandler(wxInputHandler *inphand);
55
56 virtual bool HandleKey(wxInputConsumer *consumer,
57 const wxKeyEvent& event,
58 bool pressed);
59};
1e6feb95
VZ
60
61// ----------------------------------------------------------------------------
62// wxComboListBox is a listbox modified to be used as a popup window in a
63// combobox
64// ----------------------------------------------------------------------------
65
66class wxComboListBox : public wxListBox, public wxComboPopup
67{
68public:
69 // ctor and dtor
e051d008 70 wxComboListBox();
1e6feb95
VZ
71 virtual ~wxComboListBox();
72
73 // implement wxComboPopup methods
a340b80d
VZ
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);
1e6feb95 80
d2fde247
VZ
81 // fix virtual function hiding
82 virtual void SetSelection(int n) { DoSetSelection(n, true); }
83 void SetSelection(int n, bool select) { DoSetSelection(n, select); }
84
6f02a879
VZ
85 // used to process wxUniv actions
86 bool PerformAction(const wxControlAction& action,
87 long numArg,
88 const wxString& strArg);
89
1e6feb95 90protected:
55f095d4
VZ
91 // set m_clicked value from here
92 void OnLeftUp(wxMouseEvent& event);
93
1e6feb95 94private:
131b1fba
VZ
95 friend class wxComboBox; // it accesses our DoGetItemClientData()
96
1e6feb95
VZ
97 DECLARE_EVENT_TABLE()
98};
99
100// ----------------------------------------------------------------------------
101// event tables and such
102// ----------------------------------------------------------------------------
103
1e6feb95 104BEGIN_EVENT_TABLE(wxComboListBox, wxListBox)
55f095d4 105 EVT_LEFT_UP(wxComboListBox::OnLeftUp)
1e6feb95
VZ
106END_EVENT_TABLE()
107
1e6feb95
VZ
108// ============================================================================
109// implementation
110// ============================================================================
111
112// ----------------------------------------------------------------------------
a340b80d 113// wxComboListBox
1e6feb95
VZ
114// ----------------------------------------------------------------------------
115
e051d008 116wxComboListBox::wxComboListBox() : wxListBox(), wxComboPopup()
1e6feb95 117{
1e6feb95
VZ
118}
119
a340b80d 120bool wxComboListBox::Create(wxWindow* parent)
1e6feb95 121{
a340b80d
VZ
122 if ( !wxListBox::Create(parent, wxID_ANY,
123 wxDefaultPosition, wxDefaultSize,
124 0, NULL,
750040fa
WS
125 wxBORDER_SIMPLE |
126 ( m_combo->GetWindowStyle() & wxCB_SORT ? wxLB_SORT : 0 ) ) )
a290fa5a 127 return false;
1e6feb95 128
a340b80d
VZ
129 // we don't react to the mouse events outside the window at all
130 StopAutoScrolling();
1e6feb95 131
a290fa5a 132 return true;
1e6feb95
VZ
133}
134
a340b80d 135wxComboListBox::~wxComboListBox()
1e6feb95 136{
1e6feb95
VZ
137}
138
a340b80d 139wxString wxComboListBox::GetStringValue() const
1e6feb95 140{
a340b80d 141 return wxListBox::GetStringSelection();
1e6feb95
VZ
142}
143
a340b80d 144void wxComboListBox::SetStringValue(const wxString& value)
1e6feb95 145{
615a96e3
JS
146 if ( !value.empty() )
147 {
f6fc052a
JS
148 if (FindString(value) != wxNOT_FOUND)
149 wxListBox::SetStringSelection(value);
150 }
a340b80d
VZ
151 else
152 wxListBox::SetSelection(-1);
1e6feb95
VZ
153}
154
a340b80d 155void wxComboListBox::OnPopup()
1e6feb95
VZ
156{
157}
158
159bool wxComboListBox::PerformAction(const wxControlAction& action,
160 long numArg,
161 const wxString& strArg)
162
163{
164 if ( action == wxACTION_LISTBOX_FIND )
165 {
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
a57d600f 168 // and this is done by wxComboCtrl itself
a290fa5a 169 return true;
1e6feb95
VZ
170 }
171
172 return wxListBox::PerformAction(action, numArg, strArg);
173}
174
55f095d4
VZ
175void wxComboListBox::OnLeftUp(wxMouseEvent& event)
176{
177 // we should dismiss the combo now
a340b80d
VZ
178 // first update the combo and close the listbox
179 Dismiss();
180 m_combo->SetValue(wxListBox::GetStringSelection());
55f095d4 181
a340b80d
VZ
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);
3b7fa206 186 m_combo->ProcessWindowEvent(evt);
55f095d4 187
a340b80d 188 event.Skip();
e2ca829e
JS
189}
190
a340b80d
VZ
191wxSize wxComboListBox::GetAdjustedSize(int minWidth,
192 int WXUNUSED(prefHeight),
193 int maxHeight)
1e6feb95 194{
a340b80d
VZ
195 wxSize bestSize = wxListBox::GetBestSize();
196 return wxSize(wxMax(bestSize.x,minWidth),
197 wxMin(bestSize.y,maxHeight));
1e6feb95
VZ
198}
199
200// ----------------------------------------------------------------------------
201// wxComboBox
202// ----------------------------------------------------------------------------
203
204void wxComboBox::Init()
205{
d3b9f782 206 m_lbox = NULL;
1e6feb95
VZ
207}
208
584ad2a3
MB
209wxComboBox::wxComboBox(wxWindow *parent,
210 wxWindowID id,
211 const wxString& value,
212 const wxPoint& pos,
213 const wxSize& size,
214 const wxArrayString& choices,
215 long style,
216 const wxValidator& validator,
217 const wxString& name)
218{
219 Init();
220
221 Create(parent, id, value, pos, size, choices, style, validator, name);
222}
223
224bool wxComboBox::Create(wxWindow *parent,
225 wxWindowID id,
226 const wxString& value,
227 const wxPoint& pos,
228 const wxSize& size,
229 const wxArrayString& choices,
230 long style,
231 const wxValidator& validator,
232 const wxString& name)
233{
234 wxCArrayString chs(choices);
235
236 return Create(parent, id, value, pos, size, chs.GetCount(),
237 chs.GetStrings(), style, validator, name);
238}
239
1e6feb95
VZ
240bool wxComboBox::Create(wxWindow *parent,
241 wxWindowID id,
242 const wxString& value,
243 const wxPoint& pos,
244 const wxSize& size,
245 int n,
ba1e9d6c 246 const wxString choices[],
1e6feb95
VZ
247 long style,
248 const wxValidator& validator,
249 const wxString& name)
250{
a57d600f 251 if ( !wxComboCtrl::Create(parent, id, value, pos, size, style,
1e6feb95
VZ
252 validator, name) )
253 {
a290fa5a 254 return false;
1e6feb95
VZ
255 }
256
e051d008 257 wxComboListBox *combolbox = new wxComboListBox();
a340b80d
VZ
258 SetPopupControl(combolbox);
259
1e6feb95
VZ
260 m_lbox = combolbox;
261 m_lbox->Set(n, choices);
262
a290fa5a 263 return true;
1e6feb95
VZ
264}
265
266wxComboBox::~wxComboBox()
267{
268}
269
270// ----------------------------------------------------------------------------
271// wxComboBox methods forwarded to wxTextCtrl
272// ----------------------------------------------------------------------------
273
3373e900 274wxString wxComboBox::DoGetValue() const
1e6feb95 275{
0aae39ef 276 return GetTextCtrl() ? GetTextCtrl()->GetValue() : wxString();
1e6feb95
VZ
277}
278
279void wxComboBox::SetValue(const wxString& value)
280{
0aae39ef
VZ
281 if ( GetTextCtrl() )
282 GetTextCtrl()->SetValue(value);
1e6feb95
VZ
283}
284
0ec1179b
VZ
285void wxComboBox::WriteText(const wxString& value)
286{
287 if ( GetTextCtrl() ) GetTextCtrl()->WriteText(value);
288}
289
1e6feb95
VZ
290void wxComboBox::Copy()
291{
a340b80d 292 if ( GetTextCtrl() ) GetTextCtrl()->Copy();
1e6feb95
VZ
293}
294
295void wxComboBox::Cut()
296{
a340b80d 297 if ( GetTextCtrl() ) GetTextCtrl()->Cut();
1e6feb95
VZ
298}
299
300void wxComboBox::Paste()
301{
a340b80d 302 if ( GetTextCtrl() ) GetTextCtrl()->Paste();
1e6feb95
VZ
303}
304
305void wxComboBox::SetInsertionPoint(long pos)
306{
a340b80d 307 if ( GetTextCtrl() ) GetTextCtrl()->SetInsertionPoint(pos);
1e6feb95
VZ
308}
309
310void wxComboBox::SetInsertionPointEnd()
311{
a340b80d 312 if ( GetTextCtrl() ) GetTextCtrl()->SetInsertionPointEnd();
1e6feb95
VZ
313}
314
315long wxComboBox::GetInsertionPoint() const
316{
a340b80d
VZ
317 if ( GetTextCtrl() )
318 return GetTextCtrl()->GetInsertionPoint();
319 return -1;
1e6feb95
VZ
320}
321
7d8268a1 322wxTextPos wxComboBox::GetLastPosition() const
1e6feb95 323{
a340b80d
VZ
324 if ( GetTextCtrl() )
325 return GetTextCtrl()->GetLastPosition();
326 return -1;
1e6feb95
VZ
327}
328
329void wxComboBox::Replace(long from, long to, const wxString& value)
330{
a340b80d 331 if ( GetTextCtrl() ) GetTextCtrl()->Replace(from, to, value);
1e6feb95
VZ
332}
333
334void wxComboBox::Remove(long from, long to)
335{
a340b80d 336 if ( GetTextCtrl() ) GetTextCtrl()->Remove(from, to);
1e6feb95
VZ
337}
338
339void wxComboBox::SetSelection(long from, long to)
340{
a340b80d 341 if ( GetTextCtrl() ) GetTextCtrl()->SetSelection(from, to);
1e6feb95
VZ
342}
343
0ec1179b
VZ
344void wxComboBox::GetSelection(long *from, long *to) const
345{
346 if ( GetTextCtrl() ) GetTextCtrl()->GetSelection(from, to);
347}
348
1e6feb95
VZ
349void wxComboBox::SetEditable(bool editable)
350{
a340b80d 351 if ( GetTextCtrl() ) GetTextCtrl()->SetEditable(editable);
1e6feb95
VZ
352}
353
354// ----------------------------------------------------------------------------
355// wxComboBox methods forwarded to wxListBox
356// ----------------------------------------------------------------------------
357
a236aa20 358void wxComboBox::DoClear()
1e6feb95
VZ
359{
360 GetLBox()->Clear();
a340b80d 361 if ( GetTextCtrl() ) GetTextCtrl()->SetValue(wxEmptyString);
1e6feb95
VZ
362}
363
a236aa20 364void wxComboBox::DoDeleteOneItem(unsigned int n)
1e6feb95 365{
9a83f860 366 wxCHECK_RET( IsValid(n), wxT("invalid index in wxComboBox::Delete") );
48aa18c0 367
aa61d352 368 if (GetSelection() == (int)n)
a340b80d 369 if ( GetTextCtrl() ) GetTextCtrl()->SetValue(wxEmptyString);
48aa18c0 370
1e6feb95
VZ
371 GetLBox()->Delete(n);
372}
373
aa61d352 374unsigned int wxComboBox::GetCount() const
1e6feb95
VZ
375{
376 return GetLBox()->GetCount();
377}
378
aa61d352 379wxString wxComboBox::GetString(unsigned int n) const
1e6feb95 380{
9a83f860 381 wxCHECK_MSG( IsValid(n), wxEmptyString, wxT("invalid index in wxComboBox::GetString") );
48aa18c0 382
1e6feb95
VZ
383 return GetLBox()->GetString(n);
384}
385
aa61d352 386void wxComboBox::SetString(unsigned int n, const wxString& s)
1e6feb95 387{
9a83f860 388 wxCHECK_RET( IsValid(n), wxT("invalid index in wxComboBox::SetString") );
48aa18c0 389
1e6feb95
VZ
390 GetLBox()->SetString(n, s);
391}
392
11e62fe6 393int wxComboBox::FindString(const wxString& s, bool bCase) const
1e6feb95 394{
11e62fe6 395 return GetLBox()->FindString(s, bCase);
1e6feb95
VZ
396}
397
c6179a84 398void wxComboBox::SetSelection(int n)
1e6feb95 399{
9a83f860 400 wxCHECK_RET( (n == wxNOT_FOUND || IsValid(n)), wxT("invalid index in wxComboBox::Select") );
1e6feb95
VZ
401
402 GetLBox()->SetSelection(n);
365271b5 403
75a788ee
VZ
404 wxString str;
405 if ( n != wxNOT_FOUND )
406 str = GetLBox()->GetString(n);
407
408 SetText(str);
1e6feb95
VZ
409}
410
411int wxComboBox::GetSelection() const
412{
4c51a665 413#if 1 // FIXME:: What is the correct behaviour?
1e6feb95 414 // if the current value isn't one of the listbox strings, return -1
48aa18c0 415 return GetLBox()->GetSelection();
150e31d2
JS
416#else
417 // Why oh why is this done this way?
418 // It is not because the value displayed in the text can be found
48aa18c0 419 // in the list that it is the item that is selected!
a340b80d 420 return FindString(if ( GetTextCtrl() ) GetTextCtrl()->GetValue());
48aa18c0 421#endif
1e6feb95
VZ
422}
423
0ec1179b
VZ
424wxString wxComboBox::GetStringSelection() const
425{
426 return GetLBox()->GetStringSelection();
427}
428
b152d8c5
VZ
429wxClientDataType wxComboBox::GetClientDataType() const
430{
431 return GetLBox()->GetClientDataType();
432}
433
131b1fba
VZ
434void wxComboBox::SetClientDataType(wxClientDataType clientDataItemsType)
435{
436 GetLBox()->SetClientDataType(clientDataItemsType);
437}
438
a236aa20
VZ
439int wxComboBox::DoInsertItems(const wxArrayStringsAdapter & items,
440 unsigned int pos,
441 void **clientData, wxClientDataType type)
1e6feb95 442{
a236aa20 443 return GetLBox()->DoInsertItems(items, pos, clientData, type);
243dbf1a
VZ
444}
445
aa61d352 446void wxComboBox::DoSetItemClientData(unsigned int n, void* clientData)
1e6feb95 447{
131b1fba 448 GetLBox()->DoSetItemClientData(n, clientData);
1e6feb95
VZ
449}
450
aa61d352 451void *wxComboBox::DoGetItemClientData(unsigned int n) const
1e6feb95 452{
131b1fba 453 return GetLBox()->DoGetItemClientData(n);
1e6feb95
VZ
454}
455
150e31d2
JS
456bool wxComboBox::IsEditable() const
457{
a340b80d 458 return GetTextCtrl() != NULL && (!HasFlag(wxCB_READONLY) || GetTextCtrl()->IsEditable() );
150e31d2
JS
459}
460
461void wxComboBox::Undo()
462{
463 if (IsEditable())
a340b80d 464 if ( GetTextCtrl() ) GetTextCtrl()->Undo();
150e31d2
JS
465}
466
467void wxComboBox::Redo()
468{
469 if (IsEditable())
a340b80d 470 if ( GetTextCtrl() ) GetTextCtrl()->Redo();
150e31d2
JS
471}
472
473void wxComboBox::SelectAll()
474{
a340b80d 475 if ( GetTextCtrl() ) GetTextCtrl()->SelectAll();
150e31d2
JS
476}
477
478bool wxComboBox::CanCopy() const
479{
a340b80d
VZ
480 if (GetTextCtrl() != NULL)
481 return GetTextCtrl()->CanCopy();
150e31d2
JS
482 else
483 return false;
484}
485
486bool wxComboBox::CanCut() const
487{
a340b80d
VZ
488 if (GetTextCtrl() != NULL)
489 return GetTextCtrl()->CanCut();
150e31d2
JS
490 else
491 return false;
492}
493
494bool wxComboBox::CanPaste() const
495{
496 if (IsEditable())
a340b80d 497 return GetTextCtrl()->CanPaste();
150e31d2
JS
498 else
499 return false;
500}
501
502bool wxComboBox::CanUndo() const
503{
504 if (IsEditable())
a340b80d 505 return GetTextCtrl()->CanUndo();
150e31d2
JS
506 else
507 return false;
508}
509
510bool wxComboBox::CanRedo() const
511{
512 if (IsEditable())
a340b80d 513 return GetTextCtrl()->CanRedo();
150e31d2
JS
514 else
515 return false;
516}
517
518
1e6feb95
VZ
519// ----------------------------------------------------------------------------
520// wxStdComboBoxInputHandler
521// ----------------------------------------------------------------------------
522
523wxStdComboBoxInputHandler::wxStdComboBoxInputHandler(wxInputHandler *inphand)
524 : wxStdInputHandler(inphand)
525{
526}
527
23645bfa 528bool wxStdComboBoxInputHandler::HandleKey(wxInputConsumer *consumer,
1e6feb95
VZ
529 const wxKeyEvent& event,
530 bool pressed)
531{
532 if ( pressed )
533 {
534 wxControlAction action;
535 switch ( event.GetKeyCode() )
536 {
537 case WXK_DOWN:
538 action = wxACTION_COMBOBOX_POPUP;
539 break;
540
541 case WXK_ESCAPE:
542 action = wxACTION_COMBOBOX_DISMISS;
543 break;
544 }
545
a290fa5a 546 if ( !action.IsEmpty() )
1e6feb95 547 {
23645bfa 548 consumer->PerformAction(action);
1e6feb95 549
a290fa5a 550 return true;
1e6feb95
VZ
551 }
552 }
553
23645bfa 554 return wxStdInputHandler::HandleKey(consumer, event, pressed);
1e6feb95
VZ
555}
556
9467bdb7
VZ
557/* static */
558wxInputHandler *wxComboBox::GetStdInputHandler(wxInputHandler *handlerDef)
559{
560 static wxStdComboBoxInputHandler s_handler(handlerDef);
561
562 return &s_handler;
563}
a340b80d 564
1e6feb95 565#endif // wxUSE_COMBOBOX