]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/combobox.cpp
colors are only set if non-black, otherwise Enable(false) does not gray them out
[wxWidgets.git] / src / mac / carbon / combobox.cpp
CommitLineData
e9576ca5
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: combobox.cpp
3// Purpose: wxComboBox class
a31a5f85 4// Author: Stefan Csomor
e9576ca5 5// Modified by:
a31a5f85 6// Created: 1998-01-01
e9576ca5 7// RCS-ID: $Id$
a31a5f85 8// Copyright: (c) Stefan Csomor
65571936 9// Licence: wxWindows licence
e9576ca5
SC
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "combobox.h"
14#endif
15
16#include "wx/combobox.h"
b5a8b32f 17#include "wx/button.h"
03e11df5 18#include "wx/menu.h"
519cb848 19#include "wx/mac/uma.h"
e9576ca5 20
2f1ae414 21#if !USE_SHARED_LIBRARY
e9576ca5 22IMPLEMENT_DYNAMIC_CLASS(wxComboBox, wxControl)
2f1ae414 23#endif
e9576ca5 24
12f31626
SC
25// composite combobox implementation by Dan "Bud" Keith bud@otsys.com
26
519cb848 27
0e03d1fa 28static int nextPopUpMenuId = 1000 ;
892e461e
SC
29MenuHandle NewUniqueMenu()
30{
31 MenuHandle handle = NewMenu( nextPopUpMenuId , "\pMenu" ) ;
32 nextPopUpMenuId++ ;
33 return handle ;
34}
519cb848 35
12f31626
SC
36
37// ----------------------------------------------------------------------------
38// constants
39// ----------------------------------------------------------------------------
40
41// the margin between the text control and the choice
6097743a 42#if TARGET_API_MAC_OSX
f26ca7f8
KO
43// margin should be bigger on OS X due to blue highlight
44// around text control.
45static const wxCoord MARGIN = 6;
6097743a
SC
46static const int POPUPWIDTH = 24;
47#else
f26ca7f8 48static const wxCoord MARGIN = 2;
12f31626 49static const int POPUPWIDTH = 18;
6097743a 50#endif
12f31626
SC
51static const int POPUPHEIGHT = 23;
52
53
54// ----------------------------------------------------------------------------
55// wxComboBoxText: text control forwards events to combobox
56// ----------------------------------------------------------------------------
57
58class wxComboBoxText : public wxTextCtrl
59{
60public:
61 wxComboBoxText( wxComboBox * cb )
327788ac 62 : wxTextCtrl( cb , 1 )
12f31626
SC
63 {
64 m_cb = cb;
65 }
66
67protected:
8095ef23 68 void OnChar( wxKeyEvent& event )
12f31626 69 {
eb22f2a6 70 if ( event.GetKeyCode() == WXK_RETURN )
8095ef23
SC
71 {
72 wxString value = GetValue();
73
74 if ( m_cb->GetCount() == 0 )
75 {
76 // make Enter generate "selected" event if there is only one item
77 // in the combobox - without it, it's impossible to select it at
78 // all!
79 wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() );
80 event.SetInt( 0 );
81 event.SetString( value );
82 event.SetEventObject( m_cb );
83 m_cb->GetEventHandler()->ProcessEvent( event );
84 }
85 else
86 {
87 // add the item to the list if it's not there yet
88 if ( m_cb->FindString(value) == wxNOT_FOUND )
89 {
90 m_cb->Append(value);
91 m_cb->SetStringSelection(value);
92
93 // and generate the selected event for it
94 wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() );
95 event.SetInt( m_cb->GetCount() - 1 );
96 event.SetString( value );
97 event.SetEventObject( m_cb );
98 m_cb->GetEventHandler()->ProcessEvent( event );
99 }
100
101 // This will invoke the dialog default action, such
102 // as the clicking the default button.
103
104 wxWindow *parent = GetParent();
105 while( parent && !parent->IsTopLevel() && parent->GetDefaultItem() == NULL ) {
e40298d5 106 parent = parent->GetParent() ;
8095ef23
SC
107 }
108 if ( parent && parent->GetDefaultItem() )
109 {
110 wxButton *def = wxDynamicCast(parent->GetDefaultItem(),
111 wxButton);
112 if ( def && def->IsEnabled() )
113 {
114 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
115 event.SetEventObject(def);
116 def->Command(event);
117 return ;
118 }
119 }
120
121 return;
122 }
123 }
22a70443 124
12f31626
SC
125 event.Skip();
126 }
127
128private:
129 wxComboBox *m_cb;
130
131 DECLARE_EVENT_TABLE()
132};
133
134BEGIN_EVENT_TABLE(wxComboBoxText, wxTextCtrl)
8095ef23 135 EVT_CHAR( wxComboBoxText::OnChar)
12f31626
SC
136END_EVENT_TABLE()
137
138class wxComboBoxChoice : public wxChoice
139{
140public:
141 wxComboBoxChoice(wxComboBox *cb, int style)
327788ac 142 : wxChoice( cb , 1 )
12f31626
SC
143 {
144 m_cb = cb;
145 }
146
147protected:
148 void OnChoice( wxCommandEvent& e )
149 {
150 wxString s = e.GetString();
151
152 m_cb->DelegateChoice( s );
8095ef23
SC
153 wxCommandEvent event2(wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() );
154 event2.SetInt(m_cb->GetSelection());
155 event2.SetEventObject(m_cb);
156 event2.SetString(m_cb->GetStringSelection());
157 m_cb->ProcessCommand(event2);
12f31626 158 }
6097743a
SC
159 virtual wxSize DoGetBestSize() const
160 {
161 wxSize sz = wxChoice::DoGetBestSize() ;
d0770e4a
RD
162 if (! m_cb->HasFlag(wxCB_READONLY) )
163 sz.x = POPUPWIDTH;
6097743a
SC
164 return sz ;
165 }
12f31626
SC
166
167private:
168 wxComboBox *m_cb;
169
170 DECLARE_EVENT_TABLE()
171};
172
173BEGIN_EVENT_TABLE(wxComboBoxChoice, wxChoice)
174 EVT_CHOICE(-1, wxComboBoxChoice::OnChoice)
175END_EVENT_TABLE()
176
12f31626
SC
177wxComboBox::~wxComboBox()
178{
e94e2e95
MB
179 // delete client objects
180 FreeData();
181
182 // delete the controls now, don't leave them alive even though they would
12f31626
SC
183 // still be eventually deleted by our parent - but it will be too late, the
184 // user code expects them to be gone now
f5bb2251
GD
185 if (m_text != NULL) {
186 delete m_text;
187 m_text = NULL;
188 }
189 if (m_choice != NULL) {
190 delete m_choice;
191 m_choice = NULL;
192 }
12f31626
SC
193}
194
195
196// ----------------------------------------------------------------------------
197// geometry
198// ----------------------------------------------------------------------------
199
200wxSize wxComboBox::DoGetBestSize() const
201{
88db1d64 202 if (!m_choice && !m_text)
1deb64c0 203 return GetSize();
12f31626
SC
204 wxSize size = m_choice->GetBestSize();
205
d99937cd 206 if ( m_text != NULL )
12f31626
SC
207 {
208 wxSize sizeText = m_text->GetBestSize();
f26ca7f8
KO
209 if (sizeText.y > size.y)
210 size.y = sizeText.y;
12f31626
SC
211 size.x = POPUPWIDTH + sizeText.x + MARGIN;
212 }
213
214 return size;
215}
216
217void wxComboBox::DoMoveWindow(int x, int y, int width, int height) {
218 height = POPUPHEIGHT;
f26ca7f8
KO
219 int origin = 0;
220#if TARGET_API_MAC_OSX
221 // give the controls some padding so that the text ctrl's borders
222 // and blue highlight can appear
223 origin = 4;
224#endif
225
226 wxControl::DoMoveWindow(x, y, width + origin, height + origin);
12f31626 227
d99937cd 228 if ( m_text == NULL )
12f31626 229 {
facd6764
SC
230 // we might not be fully constructed yet, therefore watch out...
231 if ( m_choice )
232 m_choice->SetSize(0, 0 , width, -1);
12f31626
SC
233 }
234 else
235 {
7854746e 236 wxCoord wText = width - POPUPWIDTH - MARGIN;
f26ca7f8
KO
237#if TARGET_API_MAC_OSX
238 // also, we need to shrink the size of the wxTextCtrl a bit
239 // to make it appear properly on OS X.
240 height -= 8;
241 wText -= 8;
242#endif
243 m_text->SetSize(origin, origin, wText, height);
244 m_choice->SetSize(origin + wText + MARGIN, 0, POPUPWIDTH, -1);
12f31626
SC
245 }
246}
247
248
249
250// ----------------------------------------------------------------------------
251// operations forwarded to the subcontrols
252// ----------------------------------------------------------------------------
253
254bool wxComboBox::Enable(bool enable)
255{
256 if ( !wxControl::Enable(enable) )
257 return FALSE;
258
12f31626
SC
259 return TRUE;
260}
261
262bool wxComboBox::Show(bool show)
263{
264 if ( !wxControl::Show(show) )
265 return FALSE;
266
12f31626
SC
267 return TRUE;
268}
269
d99937cd
GD
270void wxComboBox::SetFocus()
271{
272 if ( m_text != NULL) {
273 m_text->SetFocus();
274 }
275}
465605e0 276
12f31626 277
d99937cd
GD
278void wxComboBox::DelegateTextChanged( const wxString& value )
279{
8095ef23 280 SetStringSelection( value );
12f31626
SC
281}
282
283
284void wxComboBox::DelegateChoice( const wxString& value )
285{
286 SetStringSelection( value );
287}
288
289
584ad2a3
MB
290bool wxComboBox::Create(wxWindow *parent, wxWindowID id,
291 const wxString& value,
292 const wxPoint& pos,
293 const wxSize& size,
294 const wxArrayString& choices,
295 long style,
296 const wxValidator& validator,
297 const wxString& name)
298{
299 wxCArrayString chs( choices );
300
301 return Create( parent, id, value, pos, size, chs.GetCount(),
302 chs.GetStrings(), style, validator, name );
303}
304
305
e9576ca5
SC
306bool wxComboBox::Create(wxWindow *parent, wxWindowID id,
307 const wxString& value,
308 const wxPoint& pos,
309 const wxSize& size,
465605e0
RR
310 int n, const wxString choices[],
311 long style,
e9576ca5
SC
312 const wxValidator& validator,
313 const wxString& name)
314{
327788ac 315 if ( !wxControl::Create(parent, id, wxDefaultPosition, wxDefaultSize, style ,
12f31626
SC
316 wxDefaultValidator, name) )
317 {
318 return FALSE;
319 }
320
327788ac 321 m_choice = new wxComboBoxChoice(this, style );
12f31626
SC
322 wxSize csize = size;
323 if ( style & wxCB_READONLY )
324 {
d99937cd 325 m_text = NULL;
12f31626
SC
326 }
327 else
328 {
329 m_text = new wxComboBoxText(this);
330 if ( size.y == -1 ) {
331 csize.y = m_text->GetSize().y ;
332 }
333 }
334
335 DoSetSize(pos.x, pos.y, csize.x, csize.y);
327788ac 336
12f31626
SC
337 for ( int i = 0 ; i < n ; i++ )
338 {
465605e0 339 m_choice->DoAppend( choices[ i ] );
12f31626
SC
340 }
341
88db1d64 342 SetBestSize(size); // Needed because it is a wxControlWithItems
d3b5db4b 343
12f31626 344 return TRUE;
e9576ca5
SC
345}
346
347wxString wxComboBox::GetValue() const
348{
12f31626
SC
349 wxString result;
350
d99937cd 351 if ( m_text == NULL )
12f31626
SC
352 {
353 result = m_choice->GetString( m_choice->GetSelection() );
354 }
355 else
356 {
357 result = m_text->GetValue();
358 }
359
360 return result;
e9576ca5
SC
361}
362
46cc7c4e
SC
363int wxComboBox::GetCount() const
364{
365 return m_choice->GetCount() ;
366}
367
e9576ca5
SC
368void wxComboBox::SetValue(const wxString& value)
369{
d60de516
SC
370 int s = FindString (value);
371 if (s == wxNOT_FOUND && !HasFlag(wxCB_READONLY) )
372 {
e40298d5 373 m_choice->Append(value) ;
d60de516 374 }
e40298d5 375 SetStringSelection( value ) ;
e9576ca5
SC
376}
377
378// Clipboard operations
379void wxComboBox::Copy()
380{
d99937cd 381 if ( m_text != NULL )
12f31626
SC
382 {
383 m_text->Copy();
384 }
e9576ca5
SC
385}
386
387void wxComboBox::Cut()
388{
d99937cd 389 if ( m_text != NULL )
12f31626
SC
390 {
391 m_text->Cut();
392 }
e9576ca5
SC
393}
394
395void wxComboBox::Paste()
396{
d99937cd 397 if ( m_text != NULL )
12f31626
SC
398 {
399 m_text->Paste();
400 }
e9576ca5
SC
401}
402
403void wxComboBox::SetEditable(bool editable)
404{
d99937cd 405 if ( ( m_text == NULL ) && editable )
12f31626
SC
406 {
407 m_text = new wxComboBoxText( this );
408 }
d99937cd 409 else if ( ( m_text != NULL ) && !editable )
12f31626
SC
410 {
411 delete m_text;
d99937cd 412 m_text = NULL;
12f31626
SC
413 }
414
415 int currentX, currentY;
416 GetPosition( &currentX, &currentY );
417
418 int currentW, currentH;
419 GetSize( &currentW, &currentH );
420
421 DoMoveWindow( currentX, currentY, currentW, currentH );
e9576ca5
SC
422}
423
424void wxComboBox::SetInsertionPoint(long pos)
425{
426 // TODO
427}
428
429void wxComboBox::SetInsertionPointEnd()
430{
431 // TODO
432}
433
434long wxComboBox::GetInsertionPoint() const
435{
436 // TODO
437 return 0;
438}
439
440long wxComboBox::GetLastPosition() const
441{
442 // TODO
443 return 0;
444}
445
446void wxComboBox::Replace(long from, long to, const wxString& value)
447{
448 // TODO
449}
450
451void wxComboBox::Remove(long from, long to)
452{
453 // TODO
454}
455
456void wxComboBox::SetSelection(long from, long to)
457{
458 // TODO
459}
460
e71a0aa9 461int wxComboBox::DoAppend(const wxString& item)
e9576ca5 462{
e71a0aa9
SC
463 return m_choice->DoAppend( item ) ;
464}
465
466int wxComboBox::DoInsert(const wxString& item, int pos)
467{
468 return m_choice->DoInsert( item , pos ) ;
469}
470
471void wxComboBox::DoSetItemClientData(int n, void* clientData)
472{
f148f2ba 473 return m_choice->DoSetItemClientData( n , clientData ) ;
e71a0aa9
SC
474}
475
476void* wxComboBox::DoGetItemClientData(int n) const
477{
f148f2ba 478 return m_choice->DoGetItemClientData( n ) ;
e71a0aa9 479}
22a70443 480
e71a0aa9
SC
481void wxComboBox::DoSetItemClientObject(int n, wxClientData* clientData)
482{
f148f2ba 483 return m_choice->DoSetItemClientObject( n , clientData ) ;
e71a0aa9
SC
484}
485
486wxClientData* wxComboBox::DoGetItemClientObject(int n) const
487{
f148f2ba
MB
488 return m_choice->DoGetItemClientObject( n ) ;
489}
490
491void wxComboBox::FreeData()
492{
493 if ( HasClientObjectData() )
494 {
495 size_t count = GetCount();
496 for ( size_t n = 0; n < count; n++ )
497 {
498 SetClientObject( n, NULL );
499 }
500 }
e9576ca5
SC
501}
502
503void wxComboBox::Delete(int n)
504{
f148f2ba
MB
505 // force client object deletion
506 if( HasClientObjectData() )
507 SetClientObject( n, NULL );
12f31626 508 m_choice->Delete( n );
e9576ca5
SC
509}
510
511void wxComboBox::Clear()
512{
f148f2ba 513 FreeData();
12f31626 514 m_choice->Clear();
e9576ca5
SC
515}
516
517int wxComboBox::GetSelection() const
518{
12f31626 519 return m_choice->GetSelection();
e9576ca5
SC
520}
521
522void wxComboBox::SetSelection(int n)
523{
12f31626
SC
524 m_choice->SetSelection( n );
525
d99937cd 526 if ( m_text != NULL )
12f31626
SC
527 {
528 m_text->SetValue( GetString( n ) );
529 }
e9576ca5
SC
530}
531
532int wxComboBox::FindString(const wxString& s) const
533{
12f31626 534 return m_choice->FindString( s );
e9576ca5
SC
535}
536
537wxString wxComboBox::GetString(int n) const
538{
12f31626 539 return m_choice->GetString( n );
e9576ca5
SC
540}
541
542wxString wxComboBox::GetStringSelection() const
543{
519cb848
SC
544 int sel = GetSelection ();
545 if (sel > -1)
546 return wxString(this->GetString (sel));
547 else
427ff662 548 return wxEmptyString;
e9576ca5
SC
549}
550
551bool wxComboBox::SetStringSelection(const wxString& sel)
552{
519cb848
SC
553 int s = FindString (sel);
554 if (s > -1)
555 {
556 SetSelection (s);
557 return TRUE;
558 }
559 else
560 return FALSE;
561}
562
e71a0aa9
SC
563void wxComboBox::SetString(int n, const wxString& s)
564{
565 m_choice->SetString( n , s ) ;
566}
567
568
4c37f124 569wxInt32 wxComboBox::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
519cb848
SC
570{
571 wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_SELECTED, m_windowId );
465605e0 572 event.SetInt(GetSelection());
519cb848 573 event.SetEventObject(this);
0a67a93b 574 event.SetString(GetStringSelection());
519cb848 575 ProcessCommand(event);
4c37f124 576 return noErr ;
e9576ca5 577}
519cb848 578