]> git.saurik.com Git - wxWidgets.git/blame - src/univ/combobox.cpp
Regenerate makefiles.
[wxWidgets.git] / src / univ / combobox.cpp
CommitLineData
1e6feb95
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: univ/combobox.cpp
3// Purpose: wxComboControl and wxComboBox implementation
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)
1e6feb95
VZ
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
1e6feb95
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#ifdef __GNUG__
a3870b2f 21 #pragma implementation "univcombobox.h"
1e6feb95
VZ
22#endif
23
24#include "wx/wxprec.h"
25
26#ifdef __BORLANDC__
27 #pragma hdrstop
28#endif
29
30#if wxUSE_COMBOBOX
31
32#ifndef WX_PRECOMP
33 #include "wx/log.h"
34
35 #include "wx/button.h"
36 #include "wx/combobox.h"
37 #include "wx/listbox.h"
38 #include "wx/textctrl.h"
8cb172b4 39 #include "wx/bmpbuttn.h"
1e6feb95
VZ
40
41 #include "wx/validate.h"
42#endif
43
d4e5272b 44#include "wx/tooltip.h"
1e6feb95
VZ
45#include "wx/popupwin.h"
46
47#include "wx/univ/renderer.h"
48#include "wx/univ/inphand.h"
49#include "wx/univ/theme.h"
50
51/*
52 The keyboard event flow:
53
54 1. they always come to the text ctrl
55 2. it forwards the ones it doesn't process to the wxComboControl
56 3. which passes them to the popup window if it is popped up
57 */
58
1b489359
JS
59// constants
60// ----------------------------------------------------------------------------
61
62// the margin between the text control and the combo button
63static const wxCoord g_comboMargin = 2;
64
1e6feb95
VZ
65// ----------------------------------------------------------------------------
66// wxComboButton is just a normal button except that it sends commands to the
67// combobox and not its parent
68// ----------------------------------------------------------------------------
69
70class wxComboButton : public wxBitmapButton
71{
72public:
73 wxComboButton(wxComboControl *combo)
74 : wxBitmapButton(combo->GetParent(), -1, wxNullBitmap,
75 wxDefaultPosition, wxDefaultSize,
e4606ed9 76 wxBORDER_NONE | wxBU_EXACTFIT)
1e6feb95
VZ
77 {
78 m_combo = combo;
79
e4606ed9
VZ
80 wxBitmap bmpNormal, bmpFocus, bmpPressed, bmpDisabled;
81
82 GetRenderer()->GetComboBitmaps(&bmpNormal,
83 &bmpFocus,
84 &bmpPressed,
85 &bmpDisabled);
1e6feb95 86
1e6feb95 87 SetBitmapLabel(bmpNormal);
e4606ed9
VZ
88 SetBitmapFocus(bmpFocus.Ok() ? bmpFocus : bmpNormal);
89 SetBitmapSelected(bmpPressed.Ok() ? bmpPressed : bmpNormal);
90 SetBitmapDisabled(bmpDisabled.Ok() ? bmpDisabled : bmpNormal);
1e6feb95 91
e4606ed9 92 SetBestSize(wxDefaultSize);
1e6feb95
VZ
93 }
94
95protected:
96 void OnButton(wxCommandEvent& event) { m_combo->ShowPopup(); }
97
e4606ed9
VZ
98 virtual wxSize DoGetBestClientSize() const
99 {
100 const wxBitmap& bmp = GetBitmapLabel();
101
102 return wxSize(bmp.GetWidth(), bmp.GetHeight());
103
104 }
1e6feb95
VZ
105
106private:
107 wxComboControl *m_combo;
108
109 DECLARE_EVENT_TABLE()
110};
111
112// ----------------------------------------------------------------------------
113// wxComboListBox is a listbox modified to be used as a popup window in a
114// combobox
115// ----------------------------------------------------------------------------
116
117class wxComboListBox : public wxListBox, public wxComboPopup
118{
119public:
120 // ctor and dtor
121 wxComboListBox(wxComboControl *combo, int style = 0);
122 virtual ~wxComboListBox();
123
124 // implement wxComboPopup methods
125 virtual bool SetSelection(const wxString& value);
126 virtual wxControl *GetControl() { return this; }
127 virtual void OnShow();
128
129protected:
130 // we shouldn't return height too big from here
131 virtual wxSize DoGetBestClientSize() const;
132
133 // filter mouse move events happening outside the list box
134 void OnMouseMove(wxMouseEvent& event);
135
55f095d4
VZ
136 // set m_clicked value from here
137 void OnLeftUp(wxMouseEvent& event);
138
1e6feb95
VZ
139 // called whenever the user selects or activates a listbox item
140 void OnSelect(wxCommandEvent& event);
141
142 // used to process wxUniv actions
143 bool PerformAction(const wxControlAction& action,
144 long numArg,
145 const wxString& strArg);
146
147private:
55f095d4
VZ
148 // has the mouse been released on this control?
149 bool m_clicked;
150
1e6feb95
VZ
151 DECLARE_EVENT_TABLE()
152};
153
154// ----------------------------------------------------------------------------
155// wxComboTextCtrl is a simple text ctrl which forwards
156// wxEVT_COMMAND_TEXT_UPDATED events and all key events to the combobox
157// ----------------------------------------------------------------------------
158
159class wxComboTextCtrl : public wxTextCtrl
160{
161public:
162 wxComboTextCtrl(wxComboControl *combo,
163 const wxString& value,
164 long style,
165 const wxValidator& validator);
166
167protected:
168 void OnKey(wxKeyEvent& event);
169 void OnText(wxCommandEvent& event);
170
171private:
172 wxComboControl *m_combo;
173
174 DECLARE_EVENT_TABLE()
175};
176
177// ----------------------------------------------------------------------------
178// event tables and such
179// ----------------------------------------------------------------------------
180
181BEGIN_EVENT_TABLE(wxComboButton, wxButton)
182 EVT_BUTTON(-1, wxComboButton::OnButton)
183END_EVENT_TABLE()
184
185BEGIN_EVENT_TABLE(wxComboListBox, wxListBox)
186 EVT_LISTBOX(-1, wxComboListBox::OnSelect)
187 EVT_LISTBOX_DCLICK(-1, wxComboListBox::OnSelect)
188 EVT_MOTION(wxComboListBox::OnMouseMove)
55f095d4 189 EVT_LEFT_UP(wxComboListBox::OnLeftUp)
1e6feb95
VZ
190END_EVENT_TABLE()
191
192BEGIN_EVENT_TABLE(wxComboControl, wxControl)
193 EVT_KEY_DOWN(wxComboControl::OnKey)
194 EVT_KEY_UP(wxComboControl::OnKey)
195END_EVENT_TABLE()
196
197BEGIN_EVENT_TABLE(wxComboTextCtrl, wxTextCtrl)
198 EVT_KEY_DOWN(wxComboTextCtrl::OnKey)
199 EVT_KEY_UP(wxComboTextCtrl::OnKey)
200 EVT_TEXT(-1, wxComboTextCtrl::OnText)
201END_EVENT_TABLE()
202
4e352a3f 203IMPLEMENT_DYNAMIC_CLASS(wxComboBox, wxControl)
1e6feb95
VZ
204
205// ============================================================================
206// implementation
207// ============================================================================
208
209// ----------------------------------------------------------------------------
210// wxComboControl creation
211// ----------------------------------------------------------------------------
212
213void wxComboControl::Init()
214{
215 m_popup = (wxComboPopup *)NULL;
216 m_winPopup = (wxPopupComboWindow *)NULL;
217 m_isPopupShown = FALSE;
9f41d601
RR
218 m_btn = NULL;
219 m_text = NULL;
1e6feb95
VZ
220}
221
222bool wxComboControl::Create(wxWindow *parent,
223 wxWindowID id,
224 const wxString& value,
225 const wxPoint& pos,
226 const wxSize& size,
227 long style,
228 const wxValidator& validator,
229 const wxString& name)
230{
231 // first create our own window, i.e. the one which will contain all
232 // subcontrols
233 style &= ~wxBORDER_NONE;
234 style |= wxBORDER_SUNKEN;
235 if ( !wxControl::Create(parent, id, pos, size, style, validator, name) )
236 return FALSE;
237
238 // create the text control and the button as our siblings (*not* children),
239 // don't care about size/position here - they will be set in DoMoveWindow()
240 m_btn = new wxComboButton(this);
241 m_text = new wxComboTextCtrl(this,
242 value,
243 style & wxCB_READONLY ? wxTE_READONLY : 0,
244 validator);
245
246 // for compatibility with the other ports, the height specified is the
247 // combined height of the combobox itself and the popup
248 if ( size.y == -1 )
249 {
250 // ok, use default height for popup too
251 m_heightPopup = -1;
252 }
253 else
254 {
255 m_heightPopup = size.y - DoGetBestSize().y;
256 }
257
e4606ed9
VZ
258 SetBestSize(size);
259 Move(pos);
1e6feb95
VZ
260
261 // create the popup window immediately here to allow creating the controls
262 // with parent == GetPopupWindow() from the derived class ctor
263 m_winPopup = new wxPopupComboWindow(this);
264
265 // have to disable this window to avoid interfering it with message
266 // processing to the text and the button... but pretend it is enabled to
267 // make IsEnabled() return TRUE
268 wxControl::Enable(FALSE); // don't use non virtual Disable() here!
269 m_isEnabled = TRUE;
270
271 CreateInputHandler(wxINP_HANDLER_COMBOBOX);
272
273 return TRUE;
274}
275
276wxComboControl::~wxComboControl()
277{
278 // as the button and the text control are the parent's children and not
279 // ours, we have to delete them manually - they are not deleted
280 // automatically by wxWindows when we're deleted
281 delete m_btn;
282 delete m_text;
283
284 delete m_winPopup;
285}
286
287// ----------------------------------------------------------------------------
288// geometry stuff
289// ----------------------------------------------------------------------------
290
291void wxComboControl::DoSetSize(int x, int y,
292 int width, int height,
293 int sizeFlags)
294{
295 // combo height is always fixed
296 wxControl::DoSetSize(x, y, width, DoGetBestSize().y, sizeFlags);
297}
298
299wxSize wxComboControl::DoGetBestClientSize() const
300{
301 wxSize sizeBtn = m_btn->GetBestSize(),
302 sizeText = m_text->GetBestSize();
303
1b489359 304 return wxSize(sizeText.x + g_comboMargin + sizeBtn.x, wxMax(sizeBtn.y, sizeText.y));
1e6feb95
VZ
305}
306
307void wxComboControl::DoMoveWindow(int x, int y, int width, int height)
308{
309 wxControl::DoMoveWindow(x, y, width, height);
310
311 // position the subcontrols inside the client area
312 wxRect rectBorders = GetRenderer()->GetBorderDimensions(GetBorder());
313 x += rectBorders.x;
314 y += rectBorders.y;
315 width -= rectBorders.x + rectBorders.width;
316 height -= rectBorders.y + rectBorders.height;
317
e4606ed9 318 wxSize sizeBtn = m_btn->GetBestSize();
1e6feb95
VZ
319
320 wxCoord wText = width - sizeBtn.x;
c2ef70ec
VS
321 wxPoint p = GetParent() ? GetParent()->GetClientAreaOrigin() : wxPoint(0,0);
322 m_text->SetSize(x - p.x, y - p.y, wText, height);
323 m_btn->SetSize(x - p.x + wText, y - p.y, sizeBtn.x, height);
1e6feb95
VZ
324}
325
326// ----------------------------------------------------------------------------
327// operations
328// ----------------------------------------------------------------------------
329
330bool wxComboControl::Enable(bool enable)
331{
332 if ( !wxControl::Enable(enable) )
333 return FALSE;
334
335 m_btn->Enable(enable);
336 m_text->Enable(enable);
337
338 return TRUE;
339}
340
341bool wxComboControl::Show(bool show)
342{
343 if ( !wxControl::Show(show) )
344 return FALSE;
345
9f41d601
RR
346 if (m_btn)
347 m_btn->Show(show);
55f095d4 348
9f41d601
RR
349 if (m_text)
350 m_text->Show(show);
1e6feb95
VZ
351
352 return TRUE;
353}
354
d4e5272b
JS
355#if wxUSE_TOOLTIPS
356void wxComboControl::DoSetToolTip(wxToolTip *tooltip)
357{
358 wxControl::DoSetToolTip(tooltip);
359
360 // Set tool tip for button and text box
361 if (m_text && m_btn)
362 {
363 if (tooltip)
364 {
365 const wxString &tip = tooltip->GetTip();
366 m_text->SetToolTip(tip);
367 m_btn->SetToolTip(tip);
368 }
369 else
370 {
371 m_text->SetToolTip(NULL);
372 m_btn->SetToolTip(NULL);
373 }
374 }
375}
376#endif // wxUSE_TOOLTIPS
377
1e6feb95
VZ
378// ----------------------------------------------------------------------------
379// popup window handling
380// ----------------------------------------------------------------------------
381
382void wxComboControl::SetPopupControl(wxComboPopup *popup)
383{
384 m_popup = popup;
385}
386
387void wxComboControl::ShowPopup()
388{
389 wxCHECK_RET( m_popup, _T("no popup to show in wxComboControl") );
390 wxCHECK_RET( !IsPopupShown(), _T("popup window already shown") );
391
392 wxControl *control = m_popup->GetControl();
393
394 // size and position the popup window correctly
395 m_winPopup->SetSize(GetSize().x,
396 m_heightPopup == -1 ? control->GetBestSize().y
397 : m_heightPopup);
398 wxSize sizePopup = m_winPopup->GetClientSize();
399 control->SetSize(0, 0, sizePopup.x, sizePopup.y);
400
401 // some controls don't accept the size we give then: e.g. a listbox may
402 // require more space to show its last row
403 wxSize sizeReal = control->GetSize();
404 if ( sizeReal != sizePopup )
405 {
406 m_winPopup->SetClientSize(sizeReal);
407 }
408
409 m_winPopup->PositionNearCombo();
410
411 // show it
55f095d4 412 m_popup->OnShow();
1e6feb95
VZ
413 m_winPopup->Popup(m_text);
414 m_text->SelectAll();
415 m_popup->SetSelection(m_text->GetValue());
416
417 m_isPopupShown = TRUE;
418}
419
420void wxComboControl::HidePopup()
421{
422 wxCHECK_RET( m_popup, _T("no popup to hide in wxComboControl") );
423 wxCHECK_RET( IsPopupShown(), _T("popup window not shown") );
424
425 m_winPopup->Dismiss();
426
427 m_isPopupShown = FALSE;
428}
429
430void wxComboControl::OnSelect(const wxString& value)
431{
432 m_text->SetValue(value);
433 m_text->SelectAll();
434
435 OnDismiss();
436}
437
438void wxComboControl::OnDismiss()
439{
440 HidePopup();
441 m_text->SetFocus();
442}
443
444// ----------------------------------------------------------------------------
445// wxComboTextCtrl
446// ----------------------------------------------------------------------------
447
448wxComboTextCtrl::wxComboTextCtrl(wxComboControl *combo,
449 const wxString& value,
450 long style,
451 const wxValidator& validator)
452 : wxTextCtrl(combo->GetParent(), -1, value,
453 wxDefaultPosition, wxDefaultSize,
454 wxBORDER_NONE | style,
455 validator)
456{
457 m_combo = combo;
458}
459
460void wxComboTextCtrl::OnText(wxCommandEvent& event)
461{
462 if ( m_combo->IsPopupShown() )
463 {
464 m_combo->GetPopupControl()->SetSelection(GetValue());
465 }
466
467 // we need to make a copy of the event to have the correct originating
468 // object and id
469 wxCommandEvent event2 = event;
470 event2.SetEventObject(m_combo);
471 event2.SetId(m_combo->GetId());
472
473 // there is a small incompatibility with wxMSW here: the combobox gets the
474 // event before the text control in our case which corresponds to SMW
475 // CBN_EDITUPDATE notification and not CBN_EDITCHANGE one wxMSW currently
476 // uses
477 //
478 // if this is really a problem, we can play games with the event handlers
479 // to circumvent this
480 (void)m_combo->ProcessEvent(event2);
481
482 event.Skip();
483}
484
485// pass the keys we don't process to the combo first
486void wxComboTextCtrl::OnKey(wxKeyEvent& event)
487{
488 switch ( event.GetKeyCode() )
489 {
490 case WXK_RETURN:
491 // the popup control gets it first but only if it is shown
492 if ( !m_combo->IsPopupShown() )
493 break;
494 //else: fall through
495
496 case WXK_UP:
497 case WXK_DOWN:
498 case WXK_ESCAPE:
499 case WXK_PAGEDOWN:
500 case WXK_PAGEUP:
501 case WXK_PRIOR:
502 case WXK_NEXT:
503 (void)m_combo->ProcessEvent(event);
504 return;
505 }
506
507 event.Skip();
508}
509
510// ----------------------------------------------------------------------------
511// wxComboListBox
512// ----------------------------------------------------------------------------
513
514wxComboListBox::wxComboListBox(wxComboControl *combo, int style)
515 : wxListBox(combo->GetPopupWindow(), -1,
516 wxDefaultPosition, wxDefaultSize,
517 0, NULL,
518 wxBORDER_SIMPLE | wxLB_INT_HEIGHT | style),
519 wxComboPopup(combo)
520{
521 // we don't react to the mouse events outside the window at all
522 StopAutoScrolling();
523}
524
525wxComboListBox::~wxComboListBox()
526{
527}
528
529bool wxComboListBox::SetSelection(const wxString& value)
530{
531 // FindItem() would just find the current item for an empty string (it
532 // always matches), but we want to show the first one in such case
533 if ( value.empty() )
534 {
535 if ( GetCount() )
536 {
537 wxListBox::SetSelection(0);
538 }
539 //else: empty listbox - nothing to do
540 }
541 else if ( !FindItem(value) )
542 {
543 // no match att all
544 return FALSE;
545 }
546
547 return TRUE;
548}
549
550void wxComboListBox::OnSelect(wxCommandEvent& event)
551{
55f095d4
VZ
552 if ( m_clicked )
553 {
554 // first update the combo and close the listbox
555 m_combo->OnSelect(event.GetString());
556
557 // next let the user code have the event
558
559 // all fields are already filled by the listbox, just change the event
560 // type and send it to the combo
561 wxCommandEvent event2 = event;
562 event2.SetEventType(wxEVT_COMMAND_COMBOBOX_SELECTED);
563 event2.SetEventObject(m_combo);
564 event2.SetId(m_combo->GetId());
565 m_combo->ProcessEvent(event2);
566 }
567 //else: ignore the events resultign from just moving the mouse initially
1e6feb95
VZ
568}
569
570void wxComboListBox::OnShow()
571{
55f095d4
VZ
572 // nobody clicked us yet
573 m_clicked = FALSE;
1e6feb95
VZ
574}
575
576bool wxComboListBox::PerformAction(const wxControlAction& action,
577 long numArg,
578 const wxString& strArg)
579
580{
581 if ( action == wxACTION_LISTBOX_FIND )
582 {
583 // we don't let the listbox handle this as instead of just using the
584 // single key presses, as usual, we use the text ctrl value as prefix
585 // and this is done by wxComboControl itself
586 return TRUE;
587 }
588
589 return wxListBox::PerformAction(action, numArg, strArg);
590}
591
55f095d4
VZ
592void wxComboListBox::OnLeftUp(wxMouseEvent& event)
593{
594 // we should dismiss the combo now
595 m_clicked = TRUE;
596
597 event.Skip();
598}
599
1e6feb95
VZ
600void wxComboListBox::OnMouseMove(wxMouseEvent& event)
601{
602 // while a wxComboListBox is shown, it always has capture, so if it doesn't
603 // we're about to go away anyhow (normally this shouldn't happen at all,
604 // but I don't put assert here as it just might do on other platforms and
605 // it doesn't break anythign anyhow)
606 if ( this == wxWindow::GetCapture() )
607 {
608 if ( HitTest(event.GetPosition()) == wxHT_WINDOW_INSIDE )
609 {
610 event.Skip();
611 }
612 //else: popup shouldn't react to the mouse motions outside it, it only
613 // captures the mouse to be able to detect when it must be
614 // dismissed, so don't call Skip()
615 }
616}
617
618wxSize wxComboListBox::DoGetBestClientSize() const
619{
620 // don't return size too big or we risk to not fit on the screen
621 wxSize size = wxListBox::DoGetBestClientSize();
622 wxCoord hChar = GetCharHeight();
623
624 int nLines = size.y / hChar;
625
626 // 10 is the same limit as used by wxMSW
627 if ( nLines > 10 )
628 {
629 size.y = 10*hChar;
630 }
631
632 return size;
633}
634
635// ----------------------------------------------------------------------------
636// wxComboBox
637// ----------------------------------------------------------------------------
638
639void wxComboBox::Init()
640{
641 m_lbox = (wxListBox *)NULL;
642}
643
644bool wxComboBox::Create(wxWindow *parent,
645 wxWindowID id,
646 const wxString& value,
647 const wxPoint& pos,
648 const wxSize& size,
649 int n,
650 const wxString *choices,
651 long style,
652 const wxValidator& validator,
653 const wxString& name)
654{
655 if ( !wxComboControl::Create(parent, id, value, pos, size, style,
656 validator, name) )
657 {
658 return FALSE;
659 }
660
661 wxComboListBox *combolbox =
662 new wxComboListBox(this, style & wxCB_SORT ? wxLB_SORT : 0);
663 m_lbox = combolbox;
664 m_lbox->Set(n, choices);
665
666 SetPopupControl(combolbox);
667
668 return TRUE;
669}
670
671wxComboBox::~wxComboBox()
672{
673}
674
675// ----------------------------------------------------------------------------
676// wxComboBox methods forwarded to wxTextCtrl
677// ----------------------------------------------------------------------------
678
679wxString wxComboBox::GetValue() const
680{
681 return GetText()->GetValue();
682}
683
684void wxComboBox::SetValue(const wxString& value)
685{
686 GetText()->SetValue(value);
687}
688
689void wxComboBox::Copy()
690{
691 GetText()->Copy();
692}
693
694void wxComboBox::Cut()
695{
696 GetText()->Cut();
697}
698
699void wxComboBox::Paste()
700{
701 GetText()->Paste();
702}
703
704void wxComboBox::SetInsertionPoint(long pos)
705{
706 GetText()->SetInsertionPoint(pos);
707}
708
709void wxComboBox::SetInsertionPointEnd()
710{
711 GetText()->SetInsertionPointEnd();
712}
713
714long wxComboBox::GetInsertionPoint() const
715{
716 return GetText()->GetInsertionPoint();
717}
718
719long wxComboBox::GetLastPosition() const
720{
721 return GetText()->GetLastPosition();
722}
723
724void wxComboBox::Replace(long from, long to, const wxString& value)
725{
726 GetText()->Replace(from, to, value);
727}
728
729void wxComboBox::Remove(long from, long to)
730{
731 GetText()->Remove(from, to);
732}
733
734void wxComboBox::SetSelection(long from, long to)
735{
736 GetText()->SetSelection(from, to);
737}
738
739void wxComboBox::SetEditable(bool editable)
740{
741 GetText()->SetEditable(editable);
742}
743
744// ----------------------------------------------------------------------------
745// wxComboBox methods forwarded to wxListBox
746// ----------------------------------------------------------------------------
747
748void wxComboBox::Clear()
749{
750 GetLBox()->Clear();
48aa18c0 751 GetText()->SetValue(wxEmptyString);
1e6feb95
VZ
752}
753
754void wxComboBox::Delete(int n)
755{
48aa18c0
JS
756 wxCHECK_RET( (n >= 0) && (n < GetCount()), _T("invalid index in wxComboBox::Delete") );
757
758 if (GetSelection() == n)
759 GetText()->SetValue(wxEmptyString);
760
1e6feb95
VZ
761 GetLBox()->Delete(n);
762}
763
764int wxComboBox::GetCount() const
765{
766 return GetLBox()->GetCount();
767}
768
769wxString wxComboBox::GetString(int n) const
770{
48aa18c0
JS
771 wxCHECK_MSG( (n >= 0) && (n < GetCount()), wxEmptyString, _T("invalid index in wxComboBox::GetString") );
772
1e6feb95
VZ
773 return GetLBox()->GetString(n);
774}
775
776void wxComboBox::SetString(int n, const wxString& s)
777{
48aa18c0
JS
778 wxCHECK_RET( (n >= 0) && (n < GetCount()), _T("invalid index in wxComboBox::SetString") );
779
1e6feb95
VZ
780 GetLBox()->SetString(n, s);
781}
782
783int wxComboBox::FindString(const wxString& s) const
784{
785 return GetLBox()->FindString(s);
786}
787
788void wxComboBox::Select(int n)
789{
48aa18c0 790 wxCHECK_RET( (n >= 0) && (n < GetCount()), _T("invalid index in wxComboBox::Select") );
1e6feb95
VZ
791
792 GetLBox()->SetSelection(n);
793 GetText()->SetValue(GetLBox()->GetString(n));
794}
795
796int wxComboBox::GetSelection() const
797{
48aa18c0 798#if 1 // FIXME:: What is the correct behavior?
1e6feb95 799 // if the current value isn't one of the listbox strings, return -1
48aa18c0
JS
800 return GetLBox()->GetSelection();
801#else
802 // Why oh why is this done this way?
803 // It is not because the value displayed in the text can be found
804 // in the list that it is the item that is selected!
1e6feb95 805 return FindString(GetText()->GetValue());
48aa18c0 806#endif
1e6feb95
VZ
807}
808
809int wxComboBox::DoAppend(const wxString& item)
810{
811 return GetLBox()->Append(item);
812}
813
814void wxComboBox::DoSetItemClientData(int n, void* clientData)
815{
816 GetLBox()->SetClientData(n, clientData);
817}
818
819void *wxComboBox::DoGetItemClientData(int n) const
820{
821 return GetLBox()->GetClientData(n);
822}
823
824void wxComboBox::DoSetItemClientObject(int n, wxClientData* clientData)
825{
826 GetLBox()->SetClientObject(n, clientData);
827}
828
829wxClientData* wxComboBox::DoGetItemClientObject(int n) const
830{
831 return GetLBox()->GetClientObject(n);
832}
833
834// ----------------------------------------------------------------------------
835// input handling
836// ----------------------------------------------------------------------------
837
2e9f62da 838void wxComboControl::OnKey(wxKeyEvent& event)
1e6feb95
VZ
839{
840 if ( m_isPopupShown )
841 {
842 // pass it to the popped up control
843 (void)m_popup->GetControl()->ProcessEvent(event);
844 }
845 else // no popup
846 {
847 event.Skip();
848 }
849}
850
851bool wxComboControl::PerformAction(const wxControlAction& action,
852 long numArg,
853 const wxString& strArg)
854{
855 bool processed = FALSE;
856 if ( action == wxACTION_COMBOBOX_POPUP )
857 {
858 if ( !m_isPopupShown )
859 {
860 ShowPopup();
861
862 processed = TRUE;
863 }
864 }
865 else if ( action == wxACTION_COMBOBOX_DISMISS )
866 {
867 if ( m_isPopupShown )
868 {
869 HidePopup();
870
871 processed = TRUE;
872 }
873 }
874
875 if ( !processed )
876 {
877 // pass along
878 return wxControl::PerformAction(action, numArg, strArg);
879 }
880
881 return TRUE;
882}
883
884// ----------------------------------------------------------------------------
885// wxStdComboBoxInputHandler
886// ----------------------------------------------------------------------------
887
888wxStdComboBoxInputHandler::wxStdComboBoxInputHandler(wxInputHandler *inphand)
889 : wxStdInputHandler(inphand)
890{
891}
892
23645bfa 893bool wxStdComboBoxInputHandler::HandleKey(wxInputConsumer *consumer,
1e6feb95
VZ
894 const wxKeyEvent& event,
895 bool pressed)
896{
897 if ( pressed )
898 {
899 wxControlAction action;
900 switch ( event.GetKeyCode() )
901 {
902 case WXK_DOWN:
903 action = wxACTION_COMBOBOX_POPUP;
904 break;
905
906 case WXK_ESCAPE:
907 action = wxACTION_COMBOBOX_DISMISS;
908 break;
909 }
910
911 if ( !!action )
912 {
23645bfa 913 consumer->PerformAction(action);
1e6feb95
VZ
914
915 return TRUE;
916 }
917 }
918
23645bfa 919 return wxStdInputHandler::HandleKey(consumer, event, pressed);
1e6feb95
VZ
920}
921
922#endif // wxUSE_COMBOBOX