Added wxPopupWindow to GTK port, wxComboBox had to
[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 sizeText = m_text->GetSize();
305
306 wxCoord wText = width - sizeBtn.x;
307 m_text->SetSize(x, y, wText, height);
308 m_btn->SetSize(x + wText, y, -1, height);
309 }
310
311 // ----------------------------------------------------------------------------
312 // operations
313 // ----------------------------------------------------------------------------
314
315 bool wxComboControl::Enable(bool enable)
316 {
317 if ( !wxControl::Enable(enable) )
318 return FALSE;
319
320 m_btn->Enable(enable);
321 m_text->Enable(enable);
322
323 return TRUE;
324 }
325
326 bool wxComboControl::Show(bool show)
327 {
328 if ( !wxControl::Show(show) )
329 return FALSE;
330
331 if (m_btn)
332 m_btn->Show(show);
333
334 if (m_text)
335 m_text->Show(show);
336
337 return TRUE;
338 }
339
340 // ----------------------------------------------------------------------------
341 // popup window handling
342 // ----------------------------------------------------------------------------
343
344 void wxComboControl::SetPopupControl(wxComboPopup *popup)
345 {
346 m_popup = popup;
347 }
348
349 void wxComboControl::ShowPopup()
350 {
351 wxCHECK_RET( m_popup, _T("no popup to show in wxComboControl") );
352 wxCHECK_RET( !IsPopupShown(), _T("popup window already shown") );
353
354 wxControl *control = m_popup->GetControl();
355
356 // size and position the popup window correctly
357 m_winPopup->SetSize(GetSize().x,
358 m_heightPopup == -1 ? control->GetBestSize().y
359 : m_heightPopup);
360 wxSize sizePopup = m_winPopup->GetClientSize();
361 control->SetSize(0, 0, sizePopup.x, sizePopup.y);
362
363 // some controls don't accept the size we give then: e.g. a listbox may
364 // require more space to show its last row
365 wxSize sizeReal = control->GetSize();
366 if ( sizeReal != sizePopup )
367 {
368 m_winPopup->SetClientSize(sizeReal);
369 }
370
371 m_winPopup->PositionNearCombo();
372
373 // show it
374 m_winPopup->Popup(m_text);
375 m_text->SelectAll();
376 m_popup->SetSelection(m_text->GetValue());
377
378 m_isPopupShown = TRUE;
379 }
380
381 void wxComboControl::HidePopup()
382 {
383 wxCHECK_RET( m_popup, _T("no popup to hide in wxComboControl") );
384 wxCHECK_RET( IsPopupShown(), _T("popup window not shown") );
385
386 m_winPopup->Dismiss();
387
388 m_isPopupShown = FALSE;
389 }
390
391 void wxComboControl::OnSelect(const wxString& value)
392 {
393 m_text->SetValue(value);
394 m_text->SelectAll();
395
396 OnDismiss();
397 }
398
399 void wxComboControl::OnDismiss()
400 {
401 HidePopup();
402 m_text->SetFocus();
403 }
404
405 // ----------------------------------------------------------------------------
406 // wxComboTextCtrl
407 // ----------------------------------------------------------------------------
408
409 wxComboTextCtrl::wxComboTextCtrl(wxComboControl *combo,
410 const wxString& value,
411 long style,
412 const wxValidator& validator)
413 : wxTextCtrl(combo->GetParent(), -1, value,
414 wxDefaultPosition, wxDefaultSize,
415 wxBORDER_NONE | style,
416 validator)
417 {
418 m_combo = combo;
419 }
420
421 void wxComboTextCtrl::OnText(wxCommandEvent& event)
422 {
423 if ( m_combo->IsPopupShown() )
424 {
425 m_combo->GetPopupControl()->SetSelection(GetValue());
426 }
427
428 // we need to make a copy of the event to have the correct originating
429 // object and id
430 wxCommandEvent event2 = event;
431 event2.SetEventObject(m_combo);
432 event2.SetId(m_combo->GetId());
433
434 // there is a small incompatibility with wxMSW here: the combobox gets the
435 // event before the text control in our case which corresponds to SMW
436 // CBN_EDITUPDATE notification and not CBN_EDITCHANGE one wxMSW currently
437 // uses
438 //
439 // if this is really a problem, we can play games with the event handlers
440 // to circumvent this
441 (void)m_combo->ProcessEvent(event2);
442
443 event.Skip();
444 }
445
446 // pass the keys we don't process to the combo first
447 void wxComboTextCtrl::OnKey(wxKeyEvent& event)
448 {
449 switch ( event.GetKeyCode() )
450 {
451 case WXK_RETURN:
452 // the popup control gets it first but only if it is shown
453 if ( !m_combo->IsPopupShown() )
454 break;
455 //else: fall through
456
457 case WXK_UP:
458 case WXK_DOWN:
459 case WXK_ESCAPE:
460 case WXK_PAGEDOWN:
461 case WXK_PAGEUP:
462 case WXK_PRIOR:
463 case WXK_NEXT:
464 (void)m_combo->ProcessEvent(event);
465 return;
466 }
467
468 event.Skip();
469 }
470
471 // ----------------------------------------------------------------------------
472 // wxComboListBox
473 // ----------------------------------------------------------------------------
474
475 wxComboListBox::wxComboListBox(wxComboControl *combo, int style)
476 : wxListBox(combo->GetPopupWindow(), -1,
477 wxDefaultPosition, wxDefaultSize,
478 0, NULL,
479 wxBORDER_SIMPLE | wxLB_INT_HEIGHT | style),
480 wxComboPopup(combo)
481 {
482 // we don't react to the mouse events outside the window at all
483 StopAutoScrolling();
484 }
485
486 wxComboListBox::~wxComboListBox()
487 {
488 }
489
490 bool wxComboListBox::SetSelection(const wxString& value)
491 {
492 // FindItem() would just find the current item for an empty string (it
493 // always matches), but we want to show the first one in such case
494 if ( value.empty() )
495 {
496 if ( GetCount() )
497 {
498 wxListBox::SetSelection(0);
499 }
500 //else: empty listbox - nothing to do
501 }
502 else if ( !FindItem(value) )
503 {
504 // no match att all
505 return FALSE;
506 }
507
508 return TRUE;
509 }
510
511 void wxComboListBox::OnSelect(wxCommandEvent& event)
512 {
513 // first let the user code have the event
514
515 // all fields are already filled by the listbox, just change the event
516 // type and send it to the combo
517 wxCommandEvent event2 = event;
518 event2.SetEventType(wxEVT_COMMAND_COMBOBOX_SELECTED);
519 event2.SetEventObject(m_combo);
520 event2.SetId(m_combo->GetId());
521 m_combo->ProcessEvent(event2);
522
523 // next update the combo and close the listbox
524 m_combo->OnSelect(event.GetString());
525 }
526
527 void wxComboListBox::OnShow()
528 {
529 }
530
531 bool wxComboListBox::PerformAction(const wxControlAction& action,
532 long numArg,
533 const wxString& strArg)
534
535 {
536 if ( action == wxACTION_LISTBOX_FIND )
537 {
538 // we don't let the listbox handle this as instead of just using the
539 // single key presses, as usual, we use the text ctrl value as prefix
540 // and this is done by wxComboControl itself
541 return TRUE;
542 }
543
544 return wxListBox::PerformAction(action, numArg, strArg);
545 }
546
547 void wxComboListBox::OnMouseMove(wxMouseEvent& event)
548 {
549 // while a wxComboListBox is shown, it always has capture, so if it doesn't
550 // we're about to go away anyhow (normally this shouldn't happen at all,
551 // but I don't put assert here as it just might do on other platforms and
552 // it doesn't break anythign anyhow)
553 if ( this == wxWindow::GetCapture() )
554 {
555 if ( HitTest(event.GetPosition()) == wxHT_WINDOW_INSIDE )
556 {
557 event.Skip();
558 }
559 //else: popup shouldn't react to the mouse motions outside it, it only
560 // captures the mouse to be able to detect when it must be
561 // dismissed, so don't call Skip()
562 }
563 }
564
565 wxSize wxComboListBox::DoGetBestClientSize() const
566 {
567 // don't return size too big or we risk to not fit on the screen
568 wxSize size = wxListBox::DoGetBestClientSize();
569 wxCoord hChar = GetCharHeight();
570
571 int nLines = size.y / hChar;
572
573 // 10 is the same limit as used by wxMSW
574 if ( nLines > 10 )
575 {
576 size.y = 10*hChar;
577 }
578
579 return size;
580 }
581
582 // ----------------------------------------------------------------------------
583 // wxComboBox
584 // ----------------------------------------------------------------------------
585
586 void wxComboBox::Init()
587 {
588 m_lbox = (wxListBox *)NULL;
589 }
590
591 bool wxComboBox::Create(wxWindow *parent,
592 wxWindowID id,
593 const wxString& value,
594 const wxPoint& pos,
595 const wxSize& size,
596 int n,
597 const wxString *choices,
598 long style,
599 const wxValidator& validator,
600 const wxString& name)
601 {
602 if ( !wxComboControl::Create(parent, id, value, pos, size, style,
603 validator, name) )
604 {
605 return FALSE;
606 }
607
608 wxComboListBox *combolbox =
609 new wxComboListBox(this, style & wxCB_SORT ? wxLB_SORT : 0);
610 m_lbox = combolbox;
611 m_lbox->Set(n, choices);
612
613 SetPopupControl(combolbox);
614
615 return TRUE;
616 }
617
618 wxComboBox::~wxComboBox()
619 {
620 }
621
622 // ----------------------------------------------------------------------------
623 // wxComboBox methods forwarded to wxTextCtrl
624 // ----------------------------------------------------------------------------
625
626 wxString wxComboBox::GetValue() const
627 {
628 return GetText()->GetValue();
629 }
630
631 void wxComboBox::SetValue(const wxString& value)
632 {
633 GetText()->SetValue(value);
634 }
635
636 void wxComboBox::Copy()
637 {
638 GetText()->Copy();
639 }
640
641 void wxComboBox::Cut()
642 {
643 GetText()->Cut();
644 }
645
646 void wxComboBox::Paste()
647 {
648 GetText()->Paste();
649 }
650
651 void wxComboBox::SetInsertionPoint(long pos)
652 {
653 GetText()->SetInsertionPoint(pos);
654 }
655
656 void wxComboBox::SetInsertionPointEnd()
657 {
658 GetText()->SetInsertionPointEnd();
659 }
660
661 long wxComboBox::GetInsertionPoint() const
662 {
663 return GetText()->GetInsertionPoint();
664 }
665
666 long wxComboBox::GetLastPosition() const
667 {
668 return GetText()->GetLastPosition();
669 }
670
671 void wxComboBox::Replace(long from, long to, const wxString& value)
672 {
673 GetText()->Replace(from, to, value);
674 }
675
676 void wxComboBox::Remove(long from, long to)
677 {
678 GetText()->Remove(from, to);
679 }
680
681 void wxComboBox::SetSelection(long from, long to)
682 {
683 GetText()->SetSelection(from, to);
684 }
685
686 void wxComboBox::SetEditable(bool editable)
687 {
688 GetText()->SetEditable(editable);
689 }
690
691 // ----------------------------------------------------------------------------
692 // wxComboBox methods forwarded to wxListBox
693 // ----------------------------------------------------------------------------
694
695 void wxComboBox::Clear()
696 {
697 GetLBox()->Clear();
698 }
699
700 void wxComboBox::Delete(int n)
701 {
702 GetLBox()->Delete(n);
703 }
704
705 int wxComboBox::GetCount() const
706 {
707 return GetLBox()->GetCount();
708 }
709
710 wxString wxComboBox::GetString(int n) const
711 {
712 return GetLBox()->GetString(n);
713 }
714
715 void wxComboBox::SetString(int n, const wxString& s)
716 {
717 GetLBox()->SetString(n, s);
718 }
719
720 int wxComboBox::FindString(const wxString& s) const
721 {
722 return GetLBox()->FindString(s);
723 }
724
725 void wxComboBox::Select(int n)
726 {
727 wxCHECK_RET( (n >= 0) && (n < GetCount()), _T("invalid combobox index") );
728
729 GetLBox()->SetSelection(n);
730 GetText()->SetValue(GetLBox()->GetString(n));
731 }
732
733 int wxComboBox::GetSelection() const
734 {
735 // if the current value isn't one of the listbox strings, return -1
736 return FindString(GetText()->GetValue());
737 }
738
739 int wxComboBox::DoAppend(const wxString& item)
740 {
741 return GetLBox()->Append(item);
742 }
743
744 void wxComboBox::DoSetItemClientData(int n, void* clientData)
745 {
746 GetLBox()->SetClientData(n, clientData);
747 }
748
749 void *wxComboBox::DoGetItemClientData(int n) const
750 {
751 return GetLBox()->GetClientData(n);
752 }
753
754 void wxComboBox::DoSetItemClientObject(int n, wxClientData* clientData)
755 {
756 GetLBox()->SetClientObject(n, clientData);
757 }
758
759 wxClientData* wxComboBox::DoGetItemClientObject(int n) const
760 {
761 return GetLBox()->GetClientObject(n);
762 }
763
764 // ----------------------------------------------------------------------------
765 // input handling
766 // ----------------------------------------------------------------------------
767
768 void wxComboControl::OnKey(wxCommandEvent& event)
769 {
770 if ( m_isPopupShown )
771 {
772 // pass it to the popped up control
773 (void)m_popup->GetControl()->ProcessEvent(event);
774 }
775 else // no popup
776 {
777 event.Skip();
778 }
779 }
780
781 bool wxComboControl::PerformAction(const wxControlAction& action,
782 long numArg,
783 const wxString& strArg)
784 {
785 bool processed = FALSE;
786 if ( action == wxACTION_COMBOBOX_POPUP )
787 {
788 if ( !m_isPopupShown )
789 {
790 ShowPopup();
791
792 processed = TRUE;
793 }
794 }
795 else if ( action == wxACTION_COMBOBOX_DISMISS )
796 {
797 if ( m_isPopupShown )
798 {
799 HidePopup();
800
801 processed = TRUE;
802 }
803 }
804
805 if ( !processed )
806 {
807 // pass along
808 return wxControl::PerformAction(action, numArg, strArg);
809 }
810
811 return TRUE;
812 }
813
814 // ----------------------------------------------------------------------------
815 // wxStdComboBoxInputHandler
816 // ----------------------------------------------------------------------------
817
818 wxStdComboBoxInputHandler::wxStdComboBoxInputHandler(wxInputHandler *inphand)
819 : wxStdInputHandler(inphand)
820 {
821 }
822
823 bool wxStdComboBoxInputHandler::HandleKey(wxControl *control,
824 const wxKeyEvent& event,
825 bool pressed)
826 {
827 if ( pressed )
828 {
829 wxControlAction action;
830 switch ( event.GetKeyCode() )
831 {
832 case WXK_DOWN:
833 action = wxACTION_COMBOBOX_POPUP;
834 break;
835
836 case WXK_ESCAPE:
837 action = wxACTION_COMBOBOX_DISMISS;
838 break;
839 }
840
841 if ( !!action )
842 {
843 control->PerformAction(action);
844
845 return TRUE;
846 }
847 }
848
849 return wxStdInputHandler::HandleKey(control, event, pressed);
850 }
851
852 #endif // wxUSE_COMBOBOX