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