]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/mac/carbon/combobox.cpp
rely on built-in best size...
[wxWidgets.git] / src / mac / carbon / combobox.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: combobox.cpp
3// Purpose: wxComboBox class
4// Author: Stefan Csomor
5// Modified by:
6// Created: 1998-01-01
7// RCS-ID: $Id$
8// Copyright: (c) Stefan Csomor
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "combobox.h"
14#endif
15
16#include "wx/combobox.h"
17#include "wx/button.h"
18#include "wx/menu.h"
19#include "wx/mac/uma.h"
20
21#if !USE_SHARED_LIBRARY
22IMPLEMENT_DYNAMIC_CLASS(wxComboBox, wxControl)
23#endif
24
25// composite combobox implementation by Dan "Bud" Keith bud@otsys.com
26
27
28static int nextPopUpMenuId = 1000 ;
29MenuHandle NewUniqueMenu()
30{
31 MenuHandle handle = NewMenu( nextPopUpMenuId , "\pMenu" ) ;
32 nextPopUpMenuId++ ;
33 return handle ;
34}
35
36
37// ----------------------------------------------------------------------------
38// constants
39// ----------------------------------------------------------------------------
40
41// the margin between the text control and the choice
42#if TARGET_API_MAC_OSX
43// margin should be bigger on OS X due to blue highlight
44// around text control.
45static const wxCoord MARGIN = 6;
46static const int POPUPWIDTH = 24;
47#else
48static const wxCoord MARGIN = 2;
49static const int POPUPWIDTH = 18;
50#endif
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 )
62 : wxTextCtrl( cb , 1 )
63 {
64 m_cb = cb;
65 }
66
67protected:
68 void OnChar( wxKeyEvent& event )
69 {
70 if ( event.GetKeyCode() == WXK_RETURN )
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 ) {
106 parent = parent->GetParent() ;
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 }
124
125 event.Skip();
126 }
127
128private:
129 wxComboBox *m_cb;
130
131 DECLARE_EVENT_TABLE()
132};
133
134BEGIN_EVENT_TABLE(wxComboBoxText, wxTextCtrl)
135 EVT_CHAR( wxComboBoxText::OnChar)
136END_EVENT_TABLE()
137
138class wxComboBoxChoice : public wxChoice
139{
140public:
141 wxComboBoxChoice(wxComboBox *cb, int style)
142 : wxChoice( cb , 1 )
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 );
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);
158 }
159 virtual wxSize DoGetBestSize() const
160 {
161 wxSize sz = wxChoice::DoGetBestSize() ;
162 if (! m_cb->HasFlag(wxCB_READONLY) )
163 sz.x = POPUPWIDTH;
164 return sz ;
165 }
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
177wxComboBox::~wxComboBox()
178{
179 // delete client objects
180 FreeData();
181
182 // delete the controls now, don't leave them alive even though they would
183 // still be eventually deleted by our parent - but it will be too late, the
184 // user code expects them to be gone now
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 }
193}
194
195
196// ----------------------------------------------------------------------------
197// geometry
198// ----------------------------------------------------------------------------
199
200wxSize wxComboBox::DoGetBestSize() const
201{
202 if (!m_choice && !m_text)
203 return GetSize();
204 wxSize size = m_choice->GetBestSize();
205
206 if ( m_text != NULL )
207 {
208 wxSize sizeText = m_text->GetBestSize();
209 if (sizeText.y > size.y)
210 size.y = sizeText.y;
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;
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);
227
228 if ( m_text == NULL )
229 {
230 // we might not be fully constructed yet, therefore watch out...
231 if ( m_choice )
232 m_choice->SetSize(0, 0 , width, -1);
233 }
234 else
235 {
236 wxCoord wText = width - POPUPWIDTH - MARGIN;
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);
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
259 return TRUE;
260}
261
262bool wxComboBox::Show(bool show)
263{
264 if ( !wxControl::Show(show) )
265 return FALSE;
266
267 return TRUE;
268}
269
270void wxComboBox::SetFocus()
271{
272 if ( m_text != NULL) {
273 m_text->SetFocus();
274 }
275}
276
277
278void wxComboBox::DelegateTextChanged( const wxString& value )
279{
280 SetStringSelection( value );
281}
282
283
284void wxComboBox::DelegateChoice( const wxString& value )
285{
286 SetStringSelection( value );
287}
288
289
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
306bool wxComboBox::Create(wxWindow *parent, wxWindowID id,
307 const wxString& value,
308 const wxPoint& pos,
309 const wxSize& size,
310 int n, const wxString choices[],
311 long style,
312 const wxValidator& validator,
313 const wxString& name)
314{
315 if ( !wxControl::Create(parent, id, wxDefaultPosition, wxDefaultSize, style ,
316 wxDefaultValidator, name) )
317 {
318 return FALSE;
319 }
320
321 m_choice = new wxComboBoxChoice(this, style );
322 wxSize csize = size;
323 if ( style & wxCB_READONLY )
324 {
325 m_text = NULL;
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);
336
337 for ( int i = 0 ; i < n ; i++ )
338 {
339 m_choice->DoAppend( choices[ i ] );
340 }
341
342 SetBestSize(size); // Needed because it is a wxControlWithItems
343
344 return TRUE;
345}
346
347wxString wxComboBox::GetValue() const
348{
349 wxString result;
350
351 if ( m_text == NULL )
352 {
353 result = m_choice->GetString( m_choice->GetSelection() );
354 }
355 else
356 {
357 result = m_text->GetValue();
358 }
359
360 return result;
361}
362
363int wxComboBox::GetCount() const
364{
365 return m_choice->GetCount() ;
366}
367
368void wxComboBox::SetValue(const wxString& value)
369{
370 int s = FindString (value);
371 if (s == wxNOT_FOUND && !HasFlag(wxCB_READONLY) )
372 {
373 m_choice->Append(value) ;
374 }
375 SetStringSelection( value ) ;
376}
377
378// Clipboard operations
379void wxComboBox::Copy()
380{
381 if ( m_text != NULL )
382 {
383 m_text->Copy();
384 }
385}
386
387void wxComboBox::Cut()
388{
389 if ( m_text != NULL )
390 {
391 m_text->Cut();
392 }
393}
394
395void wxComboBox::Paste()
396{
397 if ( m_text != NULL )
398 {
399 m_text->Paste();
400 }
401}
402
403void wxComboBox::SetEditable(bool editable)
404{
405 if ( ( m_text == NULL ) && editable )
406 {
407 m_text = new wxComboBoxText( this );
408 }
409 else if ( ( m_text != NULL ) && !editable )
410 {
411 delete m_text;
412 m_text = NULL;
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 );
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
461int wxComboBox::DoAppend(const wxString& item)
462{
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{
473 return m_choice->DoSetItemClientData( n , clientData ) ;
474}
475
476void* wxComboBox::DoGetItemClientData(int n) const
477{
478 return m_choice->DoGetItemClientData( n ) ;
479}
480
481void wxComboBox::DoSetItemClientObject(int n, wxClientData* clientData)
482{
483 return m_choice->DoSetItemClientObject( n , clientData ) ;
484}
485
486wxClientData* wxComboBox::DoGetItemClientObject(int n) const
487{
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 }
501}
502
503void wxComboBox::Delete(int n)
504{
505 // force client object deletion
506 if( HasClientObjectData() )
507 SetClientObject( n, NULL );
508 m_choice->Delete( n );
509}
510
511void wxComboBox::Clear()
512{
513 FreeData();
514 m_choice->Clear();
515}
516
517int wxComboBox::GetSelection() const
518{
519 return m_choice->GetSelection();
520}
521
522void wxComboBox::SetSelection(int n)
523{
524 m_choice->SetSelection( n );
525
526 if ( m_text != NULL )
527 {
528 m_text->SetValue( GetString( n ) );
529 }
530}
531
532int wxComboBox::FindString(const wxString& s) const
533{
534 return m_choice->FindString( s );
535}
536
537wxString wxComboBox::GetString(int n) const
538{
539 return m_choice->GetString( n );
540}
541
542wxString wxComboBox::GetStringSelection() const
543{
544 int sel = GetSelection ();
545 if (sel > -1)
546 return wxString(this->GetString (sel));
547 else
548 return wxEmptyString;
549}
550
551bool wxComboBox::SetStringSelection(const wxString& sel)
552{
553 int s = FindString (sel);
554 if (s > -1)
555 {
556 SetSelection (s);
557 return TRUE;
558 }
559 else
560 return FALSE;
561}
562
563void wxComboBox::SetString(int n, const wxString& s)
564{
565 m_choice->SetString( n , s ) ;
566}
567
568
569wxInt32 wxComboBox::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
570{
571 wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_SELECTED, m_windowId );
572 event.SetInt(GetSelection());
573 event.SetEventObject(this);
574 event.SetString(GetStringSelection());
575 ProcessCommand(event);
576 return noErr ;
577}
578