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