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