]> git.saurik.com Git - wxWidgets.git/blame - src/univ/combobox.cpp
Added wxBufferedDC class.
[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
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__
a3870b2f 31 #pragma implementation "univcombobox.h"
1e6feb95
VZ
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"
8cb172b4 49 #include "wx/bmpbuttn.h"
1e6feb95
VZ
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
73class wxComboButton : public wxBitmapButton
74{
75public:
76 wxComboButton(wxComboControl *combo)
77 : wxBitmapButton(combo->GetParent(), -1, wxNullBitmap,
78 wxDefaultPosition, wxDefaultSize,
e4606ed9 79 wxBORDER_NONE | wxBU_EXACTFIT)
1e6feb95
VZ
80 {
81 m_combo = combo;
82
e4606ed9
VZ
83 wxBitmap bmpNormal, bmpFocus, bmpPressed, bmpDisabled;
84
85 GetRenderer()->GetComboBitmaps(&bmpNormal,
86 &bmpFocus,
87 &bmpPressed,
88 &bmpDisabled);
1e6feb95 89
1e6feb95 90 SetBitmapLabel(bmpNormal);
e4606ed9
VZ
91 SetBitmapFocus(bmpFocus.Ok() ? bmpFocus : bmpNormal);
92 SetBitmapSelected(bmpPressed.Ok() ? bmpPressed : bmpNormal);
93 SetBitmapDisabled(bmpDisabled.Ok() ? bmpDisabled : bmpNormal);
1e6feb95 94
e4606ed9 95 SetBestSize(wxDefaultSize);
1e6feb95
VZ
96 }
97
98protected:
99 void OnButton(wxCommandEvent& event) { m_combo->ShowPopup(); }
100
e4606ed9
VZ
101 virtual wxSize DoGetBestClientSize() const
102 {
103 const wxBitmap& bmp = GetBitmapLabel();
104
105 return wxSize(bmp.GetWidth(), bmp.GetHeight());
106
107 }
1e6feb95
VZ
108
109private:
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
120class wxComboListBox : public wxListBox, public wxComboPopup
121{
122public:
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
132protected:
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
55f095d4
VZ
139 // set m_clicked value from here
140 void OnLeftUp(wxMouseEvent& event);
141
1e6feb95
VZ
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
150private:
55f095d4
VZ
151 // has the mouse been released on this control?
152 bool m_clicked;
153
1e6feb95
VZ
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
162class wxComboTextCtrl : public wxTextCtrl
163{
164public:
165 wxComboTextCtrl(wxComboControl *combo,
166 const wxString& value,
167 long style,
168 const wxValidator& validator);
169
170protected:
171 void OnKey(wxKeyEvent& event);
172 void OnText(wxCommandEvent& event);
173
174private:
175 wxComboControl *m_combo;
176
177 DECLARE_EVENT_TABLE()
178};
179
180// ----------------------------------------------------------------------------
181// event tables and such
182// ----------------------------------------------------------------------------
183
184BEGIN_EVENT_TABLE(wxComboButton, wxButton)
185 EVT_BUTTON(-1, wxComboButton::OnButton)
186END_EVENT_TABLE()
187
188BEGIN_EVENT_TABLE(wxComboListBox, wxListBox)
189 EVT_LISTBOX(-1, wxComboListBox::OnSelect)
190 EVT_LISTBOX_DCLICK(-1, wxComboListBox::OnSelect)
191 EVT_MOTION(wxComboListBox::OnMouseMove)
55f095d4 192 EVT_LEFT_UP(wxComboListBox::OnLeftUp)
1e6feb95
VZ
193END_EVENT_TABLE()
194
195BEGIN_EVENT_TABLE(wxComboControl, wxControl)
196 EVT_KEY_DOWN(wxComboControl::OnKey)
197 EVT_KEY_UP(wxComboControl::OnKey)
198END_EVENT_TABLE()
199
200BEGIN_EVENT_TABLE(wxComboTextCtrl, wxTextCtrl)
201 EVT_KEY_DOWN(wxComboTextCtrl::OnKey)
202 EVT_KEY_UP(wxComboTextCtrl::OnKey)
203 EVT_TEXT(-1, wxComboTextCtrl::OnText)
204END_EVENT_TABLE()
205
206IMPLEMENT_DYNAMIC_CLASS(wxComboBox, wxControl);
207
208// ============================================================================
209// implementation
210// ============================================================================
211
212// ----------------------------------------------------------------------------
213// wxComboControl creation
214// ----------------------------------------------------------------------------
215
216void wxComboControl::Init()
217{
218 m_popup = (wxComboPopup *)NULL;
219 m_winPopup = (wxPopupComboWindow *)NULL;
220 m_isPopupShown = FALSE;
9f41d601
RR
221 m_btn = NULL;
222 m_text = NULL;
1e6feb95
VZ
223}
224
225bool 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
e4606ed9
VZ
261 SetBestSize(size);
262 Move(pos);
1e6feb95
VZ
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
279wxComboControl::~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
294void 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
302wxSize 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
310void 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
e4606ed9 321 wxSize sizeBtn = m_btn->GetBestSize();
1e6feb95
VZ
322
323 wxCoord wText = width - sizeBtn.x;
c2ef70ec
VS
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);
1e6feb95
VZ
327}
328
329// ----------------------------------------------------------------------------
330// operations
331// ----------------------------------------------------------------------------
332
333bool 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
344bool wxComboControl::Show(bool show)
345{
346 if ( !wxControl::Show(show) )
347 return FALSE;
348
9f41d601
RR
349 if (m_btn)
350 m_btn->Show(show);
55f095d4 351
9f41d601
RR
352 if (m_text)
353 m_text->Show(show);
1e6feb95
VZ
354
355 return TRUE;
356}
357
358// ----------------------------------------------------------------------------
359// popup window handling
360// ----------------------------------------------------------------------------
361
362void wxComboControl::SetPopupControl(wxComboPopup *popup)
363{
364 m_popup = popup;
365}
366
367void 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
55f095d4 392 m_popup->OnShow();
1e6feb95
VZ
393 m_winPopup->Popup(m_text);
394 m_text->SelectAll();
395 m_popup->SetSelection(m_text->GetValue());
396
397 m_isPopupShown = TRUE;
398}
399
400void 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
410void wxComboControl::OnSelect(const wxString& value)
411{
412 m_text->SetValue(value);
413 m_text->SelectAll();
414
415 OnDismiss();
416}
417
418void wxComboControl::OnDismiss()
419{
420 HidePopup();
421 m_text->SetFocus();
422}
423
424// ----------------------------------------------------------------------------
425// wxComboTextCtrl
426// ----------------------------------------------------------------------------
427
428wxComboTextCtrl::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
440void 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
466void 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
494wxComboListBox::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
505wxComboListBox::~wxComboListBox()
506{
507}
508
509bool 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
530void wxComboListBox::OnSelect(wxCommandEvent& event)
531{
55f095d4
VZ
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
1e6feb95
VZ
548}
549
550void wxComboListBox::OnShow()
551{
55f095d4
VZ
552 // nobody clicked us yet
553 m_clicked = FALSE;
1e6feb95
VZ
554}
555
556bool 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
55f095d4
VZ
572void wxComboListBox::OnLeftUp(wxMouseEvent& event)
573{
574 // we should dismiss the combo now
575 m_clicked = TRUE;
576
577 event.Skip();
578}
579
1e6feb95
VZ
580void 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
598wxSize 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
619void wxComboBox::Init()
620{
621 m_lbox = (wxListBox *)NULL;
622}
623
624bool 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
651wxComboBox::~wxComboBox()
652{
653}
654
655// ----------------------------------------------------------------------------
656// wxComboBox methods forwarded to wxTextCtrl
657// ----------------------------------------------------------------------------
658
659wxString wxComboBox::GetValue() const
660{
661 return GetText()->GetValue();
662}
663
664void wxComboBox::SetValue(const wxString& value)
665{
666 GetText()->SetValue(value);
667}
668
669void wxComboBox::Copy()
670{
671 GetText()->Copy();
672}
673
674void wxComboBox::Cut()
675{
676 GetText()->Cut();
677}
678
679void wxComboBox::Paste()
680{
681 GetText()->Paste();
682}
683
684void wxComboBox::SetInsertionPoint(long pos)
685{
686 GetText()->SetInsertionPoint(pos);
687}
688
689void wxComboBox::SetInsertionPointEnd()
690{
691 GetText()->SetInsertionPointEnd();
692}
693
694long wxComboBox::GetInsertionPoint() const
695{
696 return GetText()->GetInsertionPoint();
697}
698
699long wxComboBox::GetLastPosition() const
700{
701 return GetText()->GetLastPosition();
702}
703
704void wxComboBox::Replace(long from, long to, const wxString& value)
705{
706 GetText()->Replace(from, to, value);
707}
708
709void wxComboBox::Remove(long from, long to)
710{
711 GetText()->Remove(from, to);
712}
713
714void wxComboBox::SetSelection(long from, long to)
715{
716 GetText()->SetSelection(from, to);
717}
718
719void wxComboBox::SetEditable(bool editable)
720{
721 GetText()->SetEditable(editable);
722}
723
724// ----------------------------------------------------------------------------
725// wxComboBox methods forwarded to wxListBox
726// ----------------------------------------------------------------------------
727
728void wxComboBox::Clear()
729{
730 GetLBox()->Clear();
731}
732
733void wxComboBox::Delete(int n)
734{
735 GetLBox()->Delete(n);
736}
737
738int wxComboBox::GetCount() const
739{
740 return GetLBox()->GetCount();
741}
742
743wxString wxComboBox::GetString(int n) const
744{
745 return GetLBox()->GetString(n);
746}
747
748void wxComboBox::SetString(int n, const wxString& s)
749{
750 GetLBox()->SetString(n, s);
751}
752
753int wxComboBox::FindString(const wxString& s) const
754{
755 return GetLBox()->FindString(s);
756}
757
758void 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
766int 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
772int wxComboBox::DoAppend(const wxString& item)
773{
774 return GetLBox()->Append(item);
775}
776
777void wxComboBox::DoSetItemClientData(int n, void* clientData)
778{
779 GetLBox()->SetClientData(n, clientData);
780}
781
782void *wxComboBox::DoGetItemClientData(int n) const
783{
784 return GetLBox()->GetClientData(n);
785}
786
787void wxComboBox::DoSetItemClientObject(int n, wxClientData* clientData)
788{
789 GetLBox()->SetClientObject(n, clientData);
790}
791
792wxClientData* wxComboBox::DoGetItemClientObject(int n) const
793{
794 return GetLBox()->GetClientObject(n);
795}
796
797// ----------------------------------------------------------------------------
798// input handling
799// ----------------------------------------------------------------------------
800
2e9f62da 801void wxComboControl::OnKey(wxKeyEvent& event)
1e6feb95
VZ
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
814bool 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
851wxStdComboBoxInputHandler::wxStdComboBoxInputHandler(wxInputHandler *inphand)
852 : wxStdInputHandler(inphand)
853{
854}
855
23645bfa 856bool wxStdComboBoxInputHandler::HandleKey(wxInputConsumer *consumer,
1e6feb95
VZ
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 {
23645bfa 876 consumer->PerformAction(action);
1e6feb95
VZ
877
878 return TRUE;
879 }
880 }
881
23645bfa 882 return wxStdInputHandler::HandleKey(consumer, event, pressed);
1e6feb95
VZ
883}
884
885#endif // wxUSE_COMBOBOX