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