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