]> git.saurik.com Git - wxWidgets.git/blame - src/univ/combobox.cpp
Applied patch [ 642157 ] [MSW] HMENU resource leak from wxMenuBar
[wxWidgets.git] / src / univ / combobox.cpp
CommitLineData
1e6feb95
VZ
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$
442b35b5 8// Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
1e6feb95
VZ
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
1e6feb95
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#ifdef __GNUG__
a3870b2f 21 #pragma implementation "univcombobox.h"
1e6feb95
VZ
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"
8cb172b4 39 #include "wx/bmpbuttn.h"
1e6feb95
VZ
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
1b489359
JS
58// constants
59// ----------------------------------------------------------------------------
60
61// the margin between the text control and the combo button
62static const wxCoord g_comboMargin = 2;
63
1e6feb95
VZ
64// ----------------------------------------------------------------------------
65// wxComboButton is just a normal button except that it sends commands to the
66// combobox and not its parent
67// ----------------------------------------------------------------------------
68
69class wxComboButton : public wxBitmapButton
70{
71public:
72 wxComboButton(wxComboControl *combo)
73 : wxBitmapButton(combo->GetParent(), -1, wxNullBitmap,
74 wxDefaultPosition, wxDefaultSize,
e4606ed9 75 wxBORDER_NONE | wxBU_EXACTFIT)
1e6feb95
VZ
76 {
77 m_combo = combo;
78
e4606ed9
VZ
79 wxBitmap bmpNormal, bmpFocus, bmpPressed, bmpDisabled;
80
81 GetRenderer()->GetComboBitmaps(&bmpNormal,
82 &bmpFocus,
83 &bmpPressed,
84 &bmpDisabled);
1e6feb95 85
1e6feb95 86 SetBitmapLabel(bmpNormal);
e4606ed9
VZ
87 SetBitmapFocus(bmpFocus.Ok() ? bmpFocus : bmpNormal);
88 SetBitmapSelected(bmpPressed.Ok() ? bmpPressed : bmpNormal);
89 SetBitmapDisabled(bmpDisabled.Ok() ? bmpDisabled : bmpNormal);
1e6feb95 90
e4606ed9 91 SetBestSize(wxDefaultSize);
1e6feb95
VZ
92 }
93
94protected:
95 void OnButton(wxCommandEvent& event) { m_combo->ShowPopup(); }
96
e4606ed9
VZ
97 virtual wxSize DoGetBestClientSize() const
98 {
99 const wxBitmap& bmp = GetBitmapLabel();
100
101 return wxSize(bmp.GetWidth(), bmp.GetHeight());
102
103 }
1e6feb95
VZ
104
105private:
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
116class wxComboListBox : public wxListBox, public wxComboPopup
117{
118public:
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
128protected:
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
55f095d4
VZ
135 // set m_clicked value from here
136 void OnLeftUp(wxMouseEvent& event);
137
1e6feb95
VZ
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
146private:
55f095d4
VZ
147 // has the mouse been released on this control?
148 bool m_clicked;
149
1e6feb95
VZ
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
158class wxComboTextCtrl : public wxTextCtrl
159{
160public:
161 wxComboTextCtrl(wxComboControl *combo,
162 const wxString& value,
163 long style,
164 const wxValidator& validator);
165
166protected:
167 void OnKey(wxKeyEvent& event);
168 void OnText(wxCommandEvent& event);
169
170private:
171 wxComboControl *m_combo;
172
173 DECLARE_EVENT_TABLE()
174};
175
176// ----------------------------------------------------------------------------
177// event tables and such
178// ----------------------------------------------------------------------------
179
180BEGIN_EVENT_TABLE(wxComboButton, wxButton)
181 EVT_BUTTON(-1, wxComboButton::OnButton)
182END_EVENT_TABLE()
183
184BEGIN_EVENT_TABLE(wxComboListBox, wxListBox)
185 EVT_LISTBOX(-1, wxComboListBox::OnSelect)
186 EVT_LISTBOX_DCLICK(-1, wxComboListBox::OnSelect)
187 EVT_MOTION(wxComboListBox::OnMouseMove)
55f095d4 188 EVT_LEFT_UP(wxComboListBox::OnLeftUp)
1e6feb95
VZ
189END_EVENT_TABLE()
190
191BEGIN_EVENT_TABLE(wxComboControl, wxControl)
192 EVT_KEY_DOWN(wxComboControl::OnKey)
193 EVT_KEY_UP(wxComboControl::OnKey)
194END_EVENT_TABLE()
195
196BEGIN_EVENT_TABLE(wxComboTextCtrl, wxTextCtrl)
197 EVT_KEY_DOWN(wxComboTextCtrl::OnKey)
198 EVT_KEY_UP(wxComboTextCtrl::OnKey)
199 EVT_TEXT(-1, wxComboTextCtrl::OnText)
200END_EVENT_TABLE()
201
4e352a3f 202IMPLEMENT_DYNAMIC_CLASS(wxComboBox, wxControl)
1e6feb95
VZ
203
204// ============================================================================
205// implementation
206// ============================================================================
207
208// ----------------------------------------------------------------------------
209// wxComboControl creation
210// ----------------------------------------------------------------------------
211
212void wxComboControl::Init()
213{
214 m_popup = (wxComboPopup *)NULL;
215 m_winPopup = (wxPopupComboWindow *)NULL;
216 m_isPopupShown = FALSE;
9f41d601
RR
217 m_btn = NULL;
218 m_text = NULL;
1e6feb95
VZ
219}
220
221bool 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
e4606ed9
VZ
257 SetBestSize(size);
258 Move(pos);
1e6feb95
VZ
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
275wxComboControl::~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
290void 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
298wxSize wxComboControl::DoGetBestClientSize() const
299{
300 wxSize sizeBtn = m_btn->GetBestSize(),
301 sizeText = m_text->GetBestSize();
302
1b489359 303 return wxSize(sizeText.x + g_comboMargin + sizeBtn.x, wxMax(sizeBtn.y, sizeText.y));
1e6feb95
VZ
304}
305
306void 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
e4606ed9 317 wxSize sizeBtn = m_btn->GetBestSize();
1e6feb95
VZ
318
319 wxCoord wText = width - sizeBtn.x;
c2ef70ec
VS
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);
1e6feb95
VZ
323}
324
325// ----------------------------------------------------------------------------
326// operations
327// ----------------------------------------------------------------------------
328
329bool 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
340bool wxComboControl::Show(bool show)
341{
342 if ( !wxControl::Show(show) )
343 return FALSE;
344
9f41d601
RR
345 if (m_btn)
346 m_btn->Show(show);
55f095d4 347
9f41d601
RR
348 if (m_text)
349 m_text->Show(show);
1e6feb95
VZ
350
351 return TRUE;
352}
353
354// ----------------------------------------------------------------------------
355// popup window handling
356// ----------------------------------------------------------------------------
357
358void wxComboControl::SetPopupControl(wxComboPopup *popup)
359{
360 m_popup = popup;
361}
362
363void 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
55f095d4 388 m_popup->OnShow();
1e6feb95
VZ
389 m_winPopup->Popup(m_text);
390 m_text->SelectAll();
391 m_popup->SetSelection(m_text->GetValue());
392
393 m_isPopupShown = TRUE;
394}
395
396void 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
406void wxComboControl::OnSelect(const wxString& value)
407{
408 m_text->SetValue(value);
409 m_text->SelectAll();
410
411 OnDismiss();
412}
413
414void wxComboControl::OnDismiss()
415{
416 HidePopup();
417 m_text->SetFocus();
418}
419
420// ----------------------------------------------------------------------------
421// wxComboTextCtrl
422// ----------------------------------------------------------------------------
423
424wxComboTextCtrl::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
436void 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
462void 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
490wxComboListBox::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
501wxComboListBox::~wxComboListBox()
502{
503}
504
505bool 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
526void wxComboListBox::OnSelect(wxCommandEvent& event)
527{
55f095d4
VZ
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
1e6feb95
VZ
544}
545
546void wxComboListBox::OnShow()
547{
55f095d4
VZ
548 // nobody clicked us yet
549 m_clicked = FALSE;
1e6feb95
VZ
550}
551
552bool 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
55f095d4
VZ
568void wxComboListBox::OnLeftUp(wxMouseEvent& event)
569{
570 // we should dismiss the combo now
571 m_clicked = TRUE;
572
573 event.Skip();
574}
575
1e6feb95
VZ
576void 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
594wxSize 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
615void wxComboBox::Init()
616{
617 m_lbox = (wxListBox *)NULL;
618}
619
620bool 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
647wxComboBox::~wxComboBox()
648{
649}
650
651// ----------------------------------------------------------------------------
652// wxComboBox methods forwarded to wxTextCtrl
653// ----------------------------------------------------------------------------
654
655wxString wxComboBox::GetValue() const
656{
657 return GetText()->GetValue();
658}
659
660void wxComboBox::SetValue(const wxString& value)
661{
662 GetText()->SetValue(value);
663}
664
665void wxComboBox::Copy()
666{
667 GetText()->Copy();
668}
669
670void wxComboBox::Cut()
671{
672 GetText()->Cut();
673}
674
675void wxComboBox::Paste()
676{
677 GetText()->Paste();
678}
679
680void wxComboBox::SetInsertionPoint(long pos)
681{
682 GetText()->SetInsertionPoint(pos);
683}
684
685void wxComboBox::SetInsertionPointEnd()
686{
687 GetText()->SetInsertionPointEnd();
688}
689
690long wxComboBox::GetInsertionPoint() const
691{
692 return GetText()->GetInsertionPoint();
693}
694
695long wxComboBox::GetLastPosition() const
696{
697 return GetText()->GetLastPosition();
698}
699
700void wxComboBox::Replace(long from, long to, const wxString& value)
701{
702 GetText()->Replace(from, to, value);
703}
704
705void wxComboBox::Remove(long from, long to)
706{
707 GetText()->Remove(from, to);
708}
709
710void wxComboBox::SetSelection(long from, long to)
711{
712 GetText()->SetSelection(from, to);
713}
714
715void wxComboBox::SetEditable(bool editable)
716{
717 GetText()->SetEditable(editable);
718}
719
720// ----------------------------------------------------------------------------
721// wxComboBox methods forwarded to wxListBox
722// ----------------------------------------------------------------------------
723
724void wxComboBox::Clear()
725{
726 GetLBox()->Clear();
727}
728
729void wxComboBox::Delete(int n)
730{
731 GetLBox()->Delete(n);
732}
733
734int wxComboBox::GetCount() const
735{
736 return GetLBox()->GetCount();
737}
738
739wxString wxComboBox::GetString(int n) const
740{
741 return GetLBox()->GetString(n);
742}
743
744void wxComboBox::SetString(int n, const wxString& s)
745{
746 GetLBox()->SetString(n, s);
747}
748
749int wxComboBox::FindString(const wxString& s) const
750{
751 return GetLBox()->FindString(s);
752}
753
754void 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
762int 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
768int wxComboBox::DoAppend(const wxString& item)
769{
770 return GetLBox()->Append(item);
771}
772
773void wxComboBox::DoSetItemClientData(int n, void* clientData)
774{
775 GetLBox()->SetClientData(n, clientData);
776}
777
778void *wxComboBox::DoGetItemClientData(int n) const
779{
780 return GetLBox()->GetClientData(n);
781}
782
783void wxComboBox::DoSetItemClientObject(int n, wxClientData* clientData)
784{
785 GetLBox()->SetClientObject(n, clientData);
786}
787
788wxClientData* wxComboBox::DoGetItemClientObject(int n) const
789{
790 return GetLBox()->GetClientObject(n);
791}
792
793// ----------------------------------------------------------------------------
794// input handling
795// ----------------------------------------------------------------------------
796
2e9f62da 797void wxComboControl::OnKey(wxKeyEvent& event)
1e6feb95
VZ
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
810bool 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
847wxStdComboBoxInputHandler::wxStdComboBoxInputHandler(wxInputHandler *inphand)
848 : wxStdInputHandler(inphand)
849{
850}
851
23645bfa 852bool wxStdComboBoxInputHandler::HandleKey(wxInputConsumer *consumer,
1e6feb95
VZ
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 {
23645bfa 872 consumer->PerformAction(action);
1e6feb95
VZ
873
874 return TRUE;
875 }
876 }
877
23645bfa 878 return wxStdInputHandler::HandleKey(consumer, event, pressed);
1e6feb95
VZ
879}
880
881#endif // wxUSE_COMBOBOX