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