]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/univ/combobox.cpp
Fix broken and missing DataView interface items for Phoenix
[wxWidgets.git] / src / univ / combobox.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/univ/combobox.cpp
3// Purpose: 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#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
26#if wxUSE_COMBOBOX
27
28#ifndef WX_PRECOMP
29 #include "wx/log.h"
30
31 #include "wx/button.h"
32 #include "wx/combobox.h"
33 #include "wx/listbox.h"
34 #include "wx/textctrl.h"
35 #include "wx/bmpbuttn.h"
36
37 #include "wx/validate.h"
38#endif
39
40#include "wx/tooltip.h"
41#include "wx/combo.h"
42
43#include "wx/univ/renderer.h"
44#include "wx/univ/inphand.h"
45#include "wx/univ/theme.h"
46
47// ----------------------------------------------------------------------------
48// wxStdComboBoxInputHandler: allows the user to open/close the combo from kbd
49// ----------------------------------------------------------------------------
50
51class WXDLLEXPORT wxStdComboBoxInputHandler : public wxStdInputHandler
52{
53public:
54 wxStdComboBoxInputHandler(wxInputHandler *inphand);
55
56 virtual bool HandleKey(wxInputConsumer *consumer,
57 const wxKeyEvent& event,
58 bool pressed);
59};
60
61// ----------------------------------------------------------------------------
62// wxComboListBox is a listbox modified to be used as a popup window in a
63// combobox
64// ----------------------------------------------------------------------------
65
66class wxComboListBox : public wxListBox, public wxComboPopup
67{
68public:
69 // ctor and dtor
70 wxComboListBox();
71 virtual ~wxComboListBox();
72
73 // implement wxComboPopup methods
74 virtual bool Create(wxWindow* parent);
75 virtual void SetStringValue(const wxString& s);
76 virtual wxString GetStringValue() const;
77 virtual wxWindow *GetControl() { return this; }
78 virtual void OnPopup();
79 virtual wxSize GetAdjustedSize(int minWidth, int prefHeight, int maxHeight);
80
81 // fix virtual function hiding
82 virtual void SetSelection(int n) { DoSetSelection(n, true); }
83 void SetSelection(int n, bool select) { DoSetSelection(n, select); }
84
85 // used to process wxUniv actions
86 bool PerformAction(const wxControlAction& action,
87 long numArg,
88 const wxString& strArg);
89
90protected:
91 // set m_clicked value from here
92 void OnLeftUp(wxMouseEvent& event);
93
94private:
95 friend class wxComboBox; // it accesses our DoGetItemClientData()
96
97 DECLARE_EVENT_TABLE()
98};
99
100// ----------------------------------------------------------------------------
101// event tables and such
102// ----------------------------------------------------------------------------
103
104BEGIN_EVENT_TABLE(wxComboListBox, wxListBox)
105 EVT_LEFT_UP(wxComboListBox::OnLeftUp)
106END_EVENT_TABLE()
107
108// ============================================================================
109// implementation
110// ============================================================================
111
112// ----------------------------------------------------------------------------
113// wxComboListBox
114// ----------------------------------------------------------------------------
115
116wxComboListBox::wxComboListBox() : wxListBox(), wxComboPopup()
117{
118}
119
120bool wxComboListBox::Create(wxWindow* parent)
121{
122 if ( !wxListBox::Create(parent, wxID_ANY,
123 wxDefaultPosition, wxDefaultSize,
124 0, NULL,
125 wxBORDER_SIMPLE |
126 ( m_combo->GetWindowStyle() & wxCB_SORT ? wxLB_SORT : 0 ) ) )
127 return false;
128
129 // we don't react to the mouse events outside the window at all
130 StopAutoScrolling();
131
132 return true;
133}
134
135wxComboListBox::~wxComboListBox()
136{
137}
138
139wxString wxComboListBox::GetStringValue() const
140{
141 return wxListBox::GetStringSelection();
142}
143
144void wxComboListBox::SetStringValue(const wxString& value)
145{
146 if ( !value.empty() )
147 {
148 if (FindString(value) != wxNOT_FOUND)
149 wxListBox::SetStringSelection(value);
150 }
151 else
152 wxListBox::SetSelection(-1);
153}
154
155void wxComboListBox::OnPopup()
156{
157}
158
159bool wxComboListBox::PerformAction(const wxControlAction& action,
160 long numArg,
161 const wxString& strArg)
162
163{
164 if ( action == wxACTION_LISTBOX_FIND )
165 {
166 // we don't let the listbox handle this as instead of just using the
167 // single key presses, as usual, we use the text ctrl value as prefix
168 // and this is done by wxComboCtrl itself
169 return true;
170 }
171
172 return wxListBox::PerformAction(action, numArg, strArg);
173}
174
175void wxComboListBox::OnLeftUp(wxMouseEvent& event)
176{
177 // we should dismiss the combo now
178 // first update the combo and close the listbox
179 Dismiss();
180 m_combo->SetValue(wxListBox::GetStringSelection());
181
182 // next let the user code have the event
183 wxCommandEvent evt(wxEVT_COMMAND_COMBOBOX_SELECTED,m_combo->GetId());
184 evt.SetInt(wxListBox::GetSelection());
185 evt.SetEventObject(m_combo);
186 m_combo->ProcessWindowEvent(evt);
187
188 event.Skip();
189}
190
191wxSize wxComboListBox::GetAdjustedSize(int minWidth,
192 int WXUNUSED(prefHeight),
193 int maxHeight)
194{
195 wxSize bestSize = wxListBox::GetBestSize();
196 return wxSize(wxMax(bestSize.x,minWidth),
197 wxMin(bestSize.y,maxHeight));
198}
199
200// ----------------------------------------------------------------------------
201// wxComboBox
202// ----------------------------------------------------------------------------
203
204void wxComboBox::Init()
205{
206 m_lbox = NULL;
207}
208
209wxComboBox::wxComboBox(wxWindow *parent,
210 wxWindowID id,
211 const wxString& value,
212 const wxPoint& pos,
213 const wxSize& size,
214 const wxArrayString& choices,
215 long style,
216 const wxValidator& validator,
217 const wxString& name)
218{
219 Init();
220
221 Create(parent, id, value, pos, size, choices, style, validator, name);
222}
223
224bool wxComboBox::Create(wxWindow *parent,
225 wxWindowID id,
226 const wxString& value,
227 const wxPoint& pos,
228 const wxSize& size,
229 const wxArrayString& choices,
230 long style,
231 const wxValidator& validator,
232 const wxString& name)
233{
234 wxCArrayString chs(choices);
235
236 return Create(parent, id, value, pos, size, chs.GetCount(),
237 chs.GetStrings(), style, validator, name);
238}
239
240bool wxComboBox::Create(wxWindow *parent,
241 wxWindowID id,
242 const wxString& value,
243 const wxPoint& pos,
244 const wxSize& size,
245 int n,
246 const wxString choices[],
247 long style,
248 const wxValidator& validator,
249 const wxString& name)
250{
251 if ( !wxComboCtrl::Create(parent, id, value, pos, size, style,
252 validator, name) )
253 {
254 return false;
255 }
256
257 wxComboListBox *combolbox = new wxComboListBox();
258 SetPopupControl(combolbox);
259
260 m_lbox = combolbox;
261 m_lbox->Set(n, choices);
262
263 return true;
264}
265
266wxComboBox::~wxComboBox()
267{
268}
269
270// ----------------------------------------------------------------------------
271// wxComboBox methods forwarded to wxTextCtrl
272// ----------------------------------------------------------------------------
273
274wxString wxComboBox::DoGetValue() const
275{
276 return GetTextCtrl() ? GetTextCtrl()->GetValue() : m_valueString;
277}
278
279void wxComboBox::SetValue(const wxString& value)
280{
281 if ( GetTextCtrl() )
282 GetTextCtrl()->SetValue(value);
283 else
284 m_valueString = value;
285}
286
287void wxComboBox::WriteText(const wxString& value)
288{
289 if ( GetTextCtrl() ) GetTextCtrl()->WriteText(value);
290}
291
292void wxComboBox::Copy()
293{
294 if ( GetTextCtrl() ) GetTextCtrl()->Copy();
295}
296
297void wxComboBox::Cut()
298{
299 if ( GetTextCtrl() ) GetTextCtrl()->Cut();
300}
301
302void wxComboBox::Paste()
303{
304 if ( GetTextCtrl() ) GetTextCtrl()->Paste();
305}
306
307void wxComboBox::SetInsertionPoint(long pos)
308{
309 if ( GetTextCtrl() ) GetTextCtrl()->SetInsertionPoint(pos);
310}
311
312void wxComboBox::SetInsertionPointEnd()
313{
314 if ( GetTextCtrl() ) GetTextCtrl()->SetInsertionPointEnd();
315}
316
317long wxComboBox::GetInsertionPoint() const
318{
319 if ( GetTextCtrl() )
320 return GetTextCtrl()->GetInsertionPoint();
321 return -1;
322}
323
324wxTextPos wxComboBox::GetLastPosition() const
325{
326 if ( GetTextCtrl() )
327 return GetTextCtrl()->GetLastPosition();
328 return -1;
329}
330
331void wxComboBox::Replace(long from, long to, const wxString& value)
332{
333 if ( GetTextCtrl() ) GetTextCtrl()->Replace(from, to, value);
334}
335
336void wxComboBox::Remove(long from, long to)
337{
338 if ( GetTextCtrl() ) GetTextCtrl()->Remove(from, to);
339}
340
341void wxComboBox::SetSelection(long from, long to)
342{
343 if ( GetTextCtrl() ) GetTextCtrl()->SetSelection(from, to);
344}
345
346void wxComboBox::GetSelection(long *from, long *to) const
347{
348 if ( GetTextCtrl() ) GetTextCtrl()->GetSelection(from, to);
349}
350
351void wxComboBox::SetEditable(bool editable)
352{
353 if ( GetTextCtrl() ) GetTextCtrl()->SetEditable(editable);
354}
355
356// ----------------------------------------------------------------------------
357// wxComboBox methods forwarded to wxListBox
358// ----------------------------------------------------------------------------
359
360void wxComboBox::DoClear()
361{
362 GetLBox()->Clear();
363 SetValue(wxEmptyString);
364}
365
366void wxComboBox::DoDeleteOneItem(unsigned int n)
367{
368 wxCHECK_RET( IsValid(n), wxT("invalid index in wxComboBox::Delete") );
369
370 if (GetSelection() == (int)n)
371 SetValue(wxEmptyString);
372
373 GetLBox()->Delete(n);
374}
375
376unsigned int wxComboBox::GetCount() const
377{
378 return GetLBox()->GetCount();
379}
380
381wxString wxComboBox::GetString(unsigned int n) const
382{
383 wxCHECK_MSG( IsValid(n), wxEmptyString, wxT("invalid index in wxComboBox::GetString") );
384
385 return GetLBox()->GetString(n);
386}
387
388void wxComboBox::SetString(unsigned int n, const wxString& s)
389{
390 wxCHECK_RET( IsValid(n), wxT("invalid index in wxComboBox::SetString") );
391
392 GetLBox()->SetString(n, s);
393}
394
395int wxComboBox::FindString(const wxString& s, bool bCase) const
396{
397 return GetLBox()->FindString(s, bCase);
398}
399
400void wxComboBox::SetSelection(int n)
401{
402 wxCHECK_RET( (n == wxNOT_FOUND || IsValid(n)), wxT("invalid index in wxComboBox::Select") );
403
404 GetLBox()->SetSelection(n);
405
406 wxString str;
407 if ( n != wxNOT_FOUND )
408 str = GetLBox()->GetString(n);
409
410 SetText(str);
411}
412
413int wxComboBox::GetSelection() const
414{
415#if 1 // FIXME:: What is the correct behaviour?
416 // if the current value isn't one of the listbox strings, return -1
417 return GetLBox()->GetSelection();
418#else
419 // Why oh why is this done this way?
420 // It is not because the value displayed in the text can be found
421 // in the list that it is the item that is selected!
422 return FindString(if ( GetTextCtrl() ) GetTextCtrl()->GetValue());
423#endif
424}
425
426wxString wxComboBox::GetStringSelection() const
427{
428 return GetLBox()->GetStringSelection();
429}
430
431wxClientDataType wxComboBox::GetClientDataType() const
432{
433 return GetLBox()->GetClientDataType();
434}
435
436void wxComboBox::SetClientDataType(wxClientDataType clientDataItemsType)
437{
438 GetLBox()->SetClientDataType(clientDataItemsType);
439}
440
441int wxComboBox::DoInsertItems(const wxArrayStringsAdapter & items,
442 unsigned int pos,
443 void **clientData, wxClientDataType type)
444{
445 return GetLBox()->DoInsertItems(items, pos, clientData, type);
446}
447
448void wxComboBox::DoSetItemClientData(unsigned int n, void* clientData)
449{
450 GetLBox()->DoSetItemClientData(n, clientData);
451}
452
453void *wxComboBox::DoGetItemClientData(unsigned int n) const
454{
455 return GetLBox()->DoGetItemClientData(n);
456}
457
458bool wxComboBox::IsEditable() const
459{
460 return GetTextCtrl() != NULL && (!HasFlag(wxCB_READONLY) || GetTextCtrl()->IsEditable() );
461}
462
463void wxComboBox::Undo()
464{
465 if (IsEditable())
466 if ( GetTextCtrl() ) GetTextCtrl()->Undo();
467}
468
469void wxComboBox::Redo()
470{
471 if (IsEditable())
472 if ( GetTextCtrl() ) GetTextCtrl()->Redo();
473}
474
475void wxComboBox::SelectAll()
476{
477 if ( GetTextCtrl() ) GetTextCtrl()->SelectAll();
478}
479
480bool wxComboBox::CanCopy() const
481{
482 if (GetTextCtrl() != NULL)
483 return GetTextCtrl()->CanCopy();
484 else
485 return false;
486}
487
488bool wxComboBox::CanCut() const
489{
490 if (GetTextCtrl() != NULL)
491 return GetTextCtrl()->CanCut();
492 else
493 return false;
494}
495
496bool wxComboBox::CanPaste() const
497{
498 if (IsEditable())
499 return GetTextCtrl()->CanPaste();
500 else
501 return false;
502}
503
504bool wxComboBox::CanUndo() const
505{
506 if (IsEditable())
507 return GetTextCtrl()->CanUndo();
508 else
509 return false;
510}
511
512bool wxComboBox::CanRedo() const
513{
514 if (IsEditable())
515 return GetTextCtrl()->CanRedo();
516 else
517 return false;
518}
519
520
521// ----------------------------------------------------------------------------
522// wxStdComboBoxInputHandler
523// ----------------------------------------------------------------------------
524
525wxStdComboBoxInputHandler::wxStdComboBoxInputHandler(wxInputHandler *inphand)
526 : wxStdInputHandler(inphand)
527{
528}
529
530bool wxStdComboBoxInputHandler::HandleKey(wxInputConsumer *consumer,
531 const wxKeyEvent& event,
532 bool pressed)
533{
534 if ( pressed )
535 {
536 wxControlAction action;
537 switch ( event.GetKeyCode() )
538 {
539 case WXK_DOWN:
540 action = wxACTION_COMBOBOX_POPUP;
541 break;
542
543 case WXK_ESCAPE:
544 action = wxACTION_COMBOBOX_DISMISS;
545 break;
546 }
547
548 if ( !action.IsEmpty() )
549 {
550 consumer->PerformAction(action);
551
552 return true;
553 }
554 }
555
556 return wxStdInputHandler::HandleKey(consumer, event, pressed);
557}
558
559/* static */
560wxInputHandler *wxComboBox::GetStdInputHandler(wxInputHandler *handlerDef)
561{
562 static wxStdComboBoxInputHandler s_handler(handlerDef);
563
564 return &s_handler;
565}
566
567#endif // wxUSE_COMBOBOX