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