]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/combobxc.cpp
introduction of m_peer
[wxWidgets.git] / src / mac / carbon / combobxc.cpp
CommitLineData
46cc7c4e
SC
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
65571936 9// Licence: wxWindows licence
46cc7c4e
SC
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"
c829d62b 20#if TARGET_API_MAC_OSX
46cc7c4e
SC
21#ifndef __HIVIEW__
22 #include <HIToolbox/HIView.h>
23#endif
c829d62b 24#endif
46cc7c4e
SC
25
26#if !USE_SHARED_LIBRARY
27IMPLEMENT_DYNAMIC_CLASS(wxComboBox, wxControl)
28#endif
29
30// composite combobox implementation by Dan "Bud" Keith bud@otsys.com
31
c829d62b 32#if TARGET_API_MAC_OSX
46cc7c4e 33#define USE_HICOMBOBOX 1 //use hi combobox define
c829d62b
SC
34#else
35#define USE_HICOMBOBOX 0
36#endif
46cc7c4e
SC
37
38static int nextPopUpMenuId = 1000 ;
39MenuHandle NewUniqueMenu()
40{
41 MenuHandle handle = NewMenu( nextPopUpMenuId , "\pMenu" ) ;
42 nextPopUpMenuId++ ;
43 return handle ;
44}
45
46
47// ----------------------------------------------------------------------------
48// constants
49// ----------------------------------------------------------------------------
50
51// the margin between the text control and the choice
52static const wxCoord MARGIN = 2;
53#if TARGET_API_MAC_OSX
54static const int POPUPWIDTH = 24;
55#else
56static const int POPUPWIDTH = 18;
57#endif
58static const int POPUPHEIGHT = 23;
59
60// ----------------------------------------------------------------------------
61// wxComboBoxText: text control forwards events to combobox
62// ----------------------------------------------------------------------------
63
64class wxComboBoxText : public wxTextCtrl
65{
66public:
67 wxComboBoxText( wxComboBox * cb )
68 : wxTextCtrl( cb , 1 )
69 {
70 m_cb = cb;
71 }
72
73protected:
74 void OnChar( wxKeyEvent& event )
75 {
76 if ( event.GetKeyCode() == WXK_RETURN )
77 {
78 wxString value = GetValue();
79
80 if ( m_cb->GetCount() == 0 )
81 {
82 // make Enter generate "selected" event if there is only one item
83 // in the combobox - without it, it's impossible to select it at
84 // all!
85 wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() );
86 event.SetInt( 0 );
87 event.SetString( value );
88 event.SetEventObject( m_cb );
89 m_cb->GetEventHandler()->ProcessEvent( event );
90 }
91 else
92 {
93 // add the item to the list if it's not there yet
94 if ( m_cb->FindString(value) == wxNOT_FOUND )
95 {
96 m_cb->Append(value);
97 m_cb->SetStringSelection(value);
98
99 // and generate the selected event for it
100 wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() );
101 event.SetInt( m_cb->GetCount() - 1 );
102 event.SetString( value );
103 event.SetEventObject( m_cb );
104 m_cb->GetEventHandler()->ProcessEvent( event );
105 }
106
107 // This will invoke the dialog default action, such
108 // as the clicking the default button.
109
110 wxWindow *parent = GetParent();
111 while( parent && !parent->IsTopLevel() && parent->GetDefaultItem() == NULL ) {
112 parent = parent->GetParent() ;
113 }
114 if ( parent && parent->GetDefaultItem() )
115 {
116 wxButton *def = wxDynamicCast(parent->GetDefaultItem(),
117 wxButton);
118 if ( def && def->IsEnabled() )
119 {
120 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
121 event.SetEventObject(def);
122 def->Command(event);
123 return ;
124 }
125 }
126
127 return;
128 }
129 }
130
131 event.Skip();
132 }
133private:
134 wxComboBox *m_cb;
135
136 DECLARE_EVENT_TABLE()
137};
138
139BEGIN_EVENT_TABLE(wxComboBoxText, wxTextCtrl)
140 EVT_CHAR( wxComboBoxText::OnChar)
141END_EVENT_TABLE()
142
143class wxComboBoxChoice : public wxChoice
144{
145public:
146 wxComboBoxChoice(wxComboBox *cb, int style)
147 : wxChoice( cb , 1 )
148 {
149 m_cb = cb;
150 }
151
152protected:
153 void OnChoice( wxCommandEvent& e )
154 {
155 wxString s = e.GetString();
156
157 m_cb->DelegateChoice( s );
158 wxCommandEvent event2(wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() );
159 event2.SetInt(m_cb->GetSelection());
160 event2.SetEventObject(m_cb);
161 event2.SetString(m_cb->GetStringSelection());
162 m_cb->ProcessCommand(event2);
163 }
164 virtual wxSize DoGetBestSize() const
165 {
166 wxSize sz = wxChoice::DoGetBestSize() ;
167 sz.x = POPUPWIDTH ;
168 return sz ;
169 }
170
171private:
172 wxComboBox *m_cb;
173
174 DECLARE_EVENT_TABLE()
175};
176
177BEGIN_EVENT_TABLE(wxComboBoxChoice, wxChoice)
178 EVT_CHOICE(-1, wxComboBoxChoice::OnChoice)
179END_EVENT_TABLE()
180
181wxComboBox::~wxComboBox()
182{
183 // delete client objects
184 FreeData();
185
186 // delete the controls now, don't leave them alive even though they would
187 // still be eventually deleted by our parent - but it will be too late, the
188 // user code expects them to be gone now
189 if (m_text != NULL) {
190 delete m_text;
191 m_text = NULL;
192 }
193 if (m_choice != NULL) {
194 delete m_choice;
195 m_choice = NULL;
196 }
197}
198
199
200// ----------------------------------------------------------------------------
201// geometry
202// ----------------------------------------------------------------------------
203
204wxSize wxComboBox::DoGetBestSize() const
205{
206#if USE_HICOMBOBOX
207 return wxControl::DoGetBestSize();
208#else
209 wxSize size = m_choice->GetBestSize();
210
211 if ( m_text != NULL )
212 {
213 wxSize sizeText = m_text->GetBestSize();
214
215 size.x = POPUPWIDTH + sizeText.x + MARGIN;
216 }
217
218 return size;
219#endif
220}
221
222void wxComboBox::DoMoveWindow(int x, int y, int width, int height) {
223#if USE_HICOMBOBOX
224 wxControl::DoMoveWindow(x, y, width, height);
225#else
226 height = POPUPHEIGHT;
227
228 wxControl::DoMoveWindow(x, y, width, height);
229
230 if ( m_text == NULL )
231 {
232 // we might not be fully constructed yet, therefore watch out...
233 if ( m_choice )
234 m_choice->SetSize(0, 0 , width, -1);
235 }
236 else
237 {
238 wxCoord wText = width - POPUPWIDTH - MARGIN;
239 m_text->SetSize(0, 0, wText, height);
240 m_choice->SetSize(0 + wText + MARGIN, 0, POPUPWIDTH, -1);
241 }
242#endif
243}
244
245
246
247// ----------------------------------------------------------------------------
248// operations forwarded to the subcontrols
249// ----------------------------------------------------------------------------
250
251bool wxComboBox::Enable(bool enable)
252{
253 if ( !wxControl::Enable(enable) )
254 return FALSE;
255
256 return TRUE;
257}
258
259bool wxComboBox::Show(bool show)
260{
261 if ( !wxControl::Show(show) )
262 return FALSE;
263
264 return TRUE;
265}
266
267void wxComboBox::SetFocus()
268{
269#if USE_HICOMBOBOX
270 wxControl::SetFocus();
271#else
272 if ( m_text != NULL) {
273 m_text->SetFocus();
274 }
275#endif
276}
277
278
279void wxComboBox::DelegateTextChanged( const wxString& value )
280{
281 SetStringSelection( value );
282}
283
284
285void wxComboBox::DelegateChoice( const wxString& value )
286{
287 SetStringSelection( value );
288}
289
290
291bool wxComboBox::Create(wxWindow *parent, wxWindowID id,
292 const wxString& value,
293 const wxPoint& pos,
294 const wxSize& size,
295 const wxArrayString& choices,
296 long style,
297 const wxValidator& validator,
298 const wxString& name)
299{
300 wxCArrayString chs( choices );
301
302 return Create( parent, id, value, pos, size, chs.GetCount(),
303 chs.GetStrings(), style, validator, name );
304}
305
306
307bool wxComboBox::Create(wxWindow *parent, wxWindowID id,
308 const wxString& value,
309 const wxPoint& pos,
310 const wxSize& size,
311 int n, const wxString choices[],
312 long style,
313 const wxValidator& validator,
314 const wxString& name)
315{
316 m_text = NULL;
317 m_choice = NULL;
318#if USE_HICOMBOBOX
319 m_macIsUserPane = FALSE ;
320#endif
321 if ( !wxControl::Create(parent, id, wxDefaultPosition, wxDefaultSize, style ,
322 wxDefaultValidator, name) )
323 {
324 return FALSE;
325 }
326#if USE_HICOMBOBOX
327 Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ;
328 HIRect hiRect;
329
330 hiRect.origin.x = 20; //bounds.left;
331 hiRect.origin.y = 25; //bounds.top;
332 hiRect.size.width = 120;// bounds.right - bounds.left;
333 hiRect.size.height = 24;
334
335 //For some reason, this code causes the combo box not to be displayed at all.
336 //hiRect.origin.x = bounds.left;
337 //hiRect.origin.y = bounds.top;
338 //hiRect.size.width = bounds.right - bounds.left;
339 //hiRect.size.height = bounds.bottom - bounds.top;
340 //printf("left = %d, right = %d, top = %d, bottom = %d\n", bounds.left, bounds.right, bounds.top, bounds.bottom);
341 //printf("x = %d, y = %d, width = %d, height = %d\n", hibounds.origin.x, hibounds.origin.y, hibounds.size.width, hibounds.size.height);
342 verify_noerr( HIComboBoxCreate( &hiRect, CFSTR(""), NULL, NULL, kHIComboBoxStandardAttributes, (HIViewRef*) &m_macControl) );
343
344 SetControl32BitMinimum( (ControlRef) m_macControl , 0 ) ;
345 SetControl32BitMaximum( (ControlRef) m_macControl , 100) ;
346 if ( n > 0 )
347 SetControl32BitValue( (ControlRef) m_macControl , 1 ) ;
348
349 MacPostControlCreate(pos,size) ;
350
351 for ( int i = 0 ; i < n ; i++ )
352 {
353 DoAppend( choices[ i ] );
354 }
355
356 HIViewSetVisible( (HIViewRef) m_macControl, true );
357 SetSelection(0);
358#else
359 m_choice = new wxComboBoxChoice(this, style );
360
361 m_choice = new wxComboBoxChoice(this, style );
362 m_choice->SetSizeHints( wxSize( POPUPWIDTH , POPUPHEIGHT ) ) ;
363
364 wxSize csize = size;
365 if ( style & wxCB_READONLY )
366 {
367 m_text = NULL;
368 }
369 else
370 {
371 m_text = new wxComboBoxText(this);
372 if ( size.y == -1 ) {
373 csize.y = m_text->GetSize().y ;
374 }
375 }
376
377 DoSetSize(pos.x, pos.y, csize.x, csize.y);
378
379 for ( int i = 0 ; i < n ; i++ )
380 {
381 m_choice->DoAppend( choices[ i ] );
382 }
383 SetBestSize(csize); // Needed because it is a wxControlWithItems
384#endif
385
386 return TRUE;
387}
388
389wxString wxComboBox::GetValue() const
390{
391#if USE_HICOMBOBOX
392 CFStringRef myString;
393 HIComboBoxCopyTextItemAtIndex( (HIViewRef) m_macControl, (CFIndex)GetSelection(), &myString );
394 return wxMacCFStringHolder( myString, m_font.GetEncoding() ).AsString();
395#else
396 wxString result;
397
398 if ( m_text == NULL )
399 {
400 result = m_choice->GetString( m_choice->GetSelection() );
401 }
402 else
403 {
404 result = m_text->GetValue();
405 }
406
407 return result;
408#endif
409}
410
411void wxComboBox::SetValue(const wxString& value)
412{
413#if USE_HICOMBOBOX
414
415#else
416 int s = FindString (value);
417 if (s == wxNOT_FOUND && !HasFlag(wxCB_READONLY) )
418 {
419 m_choice->Append(value) ;
420 }
421 SetStringSelection( value ) ;
422#endif
423}
424
425// Clipboard operations
426void wxComboBox::Copy()
427{
428 if ( m_text != NULL )
429 {
430 m_text->Copy();
431 }
432}
433
434void wxComboBox::Cut()
435{
436 if ( m_text != NULL )
437 {
438 m_text->Cut();
439 }
440}
441
442void wxComboBox::Paste()
443{
444 if ( m_text != NULL )
445 {
446 m_text->Paste();
447 }
448}
449
450void wxComboBox::SetEditable(bool editable)
451{
452 if ( ( m_text == NULL ) && editable )
453 {
454 m_text = new wxComboBoxText( this );
455 }
456 else if ( ( m_text != NULL ) && !editable )
457 {
458 delete m_text;
459 m_text = NULL;
460 }
461
462 int currentX, currentY;
463 GetPosition( &currentX, &currentY );
464
465 int currentW, currentH;
466 GetSize( &currentW, &currentH );
467
468 DoMoveWindow( currentX, currentY, currentW, currentH );
469}
470
471void wxComboBox::SetInsertionPoint(long pos)
472{
473 // TODO
474}
475
476void wxComboBox::SetInsertionPointEnd()
477{
478 // TODO
479}
480
481long wxComboBox::GetInsertionPoint() const
482{
483 // TODO
484 return 0;
485}
486
487long wxComboBox::GetLastPosition() const
488{
489 // TODO
490 return 0;
491}
492
493void wxComboBox::Replace(long from, long to, const wxString& value)
494{
495 // TODO
496}
497
498void wxComboBox::Remove(long from, long to)
499{
500 // TODO
501}
502
503void wxComboBox::SetSelection(long from, long to)
504{
505 // TODO
506}
507
508int wxComboBox::DoAppend(const wxString& item)
509{
510#if USE_HICOMBOBOX
511 CFIndex outIndex;
512 HIComboBoxAppendTextItem( (HIViewRef) m_macControl, wxMacCFStringHolder( item, m_font.GetEncoding() ), &outIndex );
513 //SetControl32BitMaximum( (HIViewRef) m_macControl, GetCount() );
514 return (int) outIndex;
515#else
516 return m_choice->DoAppend( item ) ;
517#endif
518}
519
520int wxComboBox::DoInsert(const wxString& item, int pos)
521{
522#if USE_HICOMBOBOX
523 HIComboBoxInsertTextItemAtIndex( (HIViewRef) m_macControl, (CFIndex)pos, wxMacCFStringHolder(item, m_font.GetEncoding()) );
524
525 //SetControl32BitMaximum( (HIViewRef) m_macControl, GetCount() );
526
527 return pos;
528#else
529 return m_choice->DoInsert( item , pos ) ;
530#endif
531}
532
533void wxComboBox::DoSetItemClientData(int n, void* clientData)
534{
535#if USE_HICOMBOBOX
536 return; //TODO
537#else
538 return m_choice->DoSetItemClientData( n , clientData ) ;
539#endif
540}
541
542void* wxComboBox::DoGetItemClientData(int n) const
543{
544#if USE_HICOMBOBOX
545 return NULL; //TODO
546#else
547 return m_choice->DoGetItemClientData( n ) ;
548#endif
549}
550
551void wxComboBox::DoSetItemClientObject(int n, wxClientData* clientData)
552{
553#if USE_HICOMBOBOX
554 return; //TODO
555#else
556 return m_choice->DoSetItemClientObject( n , clientData ) ;
557#endif
558}
559
560wxClientData* wxComboBox::DoGetItemClientObject(int n) const
561{
562#if USE_HICOMBOBOX
563 return NULL;
564#else
565 return m_choice->DoGetItemClientObject( n ) ;
566#endif
567}
568
569void wxComboBox::FreeData()
570{
571 if ( HasClientObjectData() )
572 {
573 size_t count = GetCount();
574 for ( size_t n = 0; n < count; n++ )
575 {
576 SetClientObject( n, NULL );
577 }
578 }
579}
580
581int wxComboBox::GetCount() const {
582#if USE_HICOMBOBOX
583 return (int) HIComboBoxGetItemCount( (HIViewRef) m_macControl );
584#else
585 return m_choice->GetCount() ;
586#endif
587}
588
589void wxComboBox::Delete(int n)
590{
591#if USE_HICOMBOBOX
592 HIComboBoxRemoveItemAtIndex( (HIViewRef) m_macControl, (CFIndex)n );
593#else
594 // force client object deletion
595 if( HasClientObjectData() )
596 SetClientObject( n, NULL );
597 m_choice->Delete( n );
598#endif
599}
600
601void wxComboBox::Clear()
602{
b310cebd 603 FreeData();
46cc7c4e 604#if USE_HICOMBOBOX
b310cebd
SC
605 for ( CFIndex i = GetCount() - 1 ; i >= 0 ; ++ i )
606 verify_noerr( HIComboBoxRemoveItemAtIndex( (HIViewRef) m_macControl, i ) );
607 wxMacCFStringHolder cf(wxEmptyString,m_font.GetEncoding()) ;
608 CFStringRef cfr = cf ;
609 SetControlData((ControlRef) m_macControl,kHIComboBoxEditTextPart,kControlEditTextCFStringTag,
610 sizeof(CFStringRef),(Ptr) &cfr);
46cc7c4e 611#else
46cc7c4e
SC
612 m_choice->Clear();
613#endif
614}
615
616int wxComboBox::GetSelection() const
617{
618#if USE_HICOMBOBOX
b310cebd 619 return FindString( GetStringSelection() ) ;
46cc7c4e
SC
620#else
621 return m_choice->GetSelection();
622#endif
623}
624
625void wxComboBox::SetSelection(int n)
626{
627#if USE_HICOMBOBOX
628 SetControl32BitValue( (ControlRef) m_macControl , n + 1 ) ;
629#else
630 m_choice->SetSelection( n );
631
632 if ( m_text != NULL )
633 {
634 m_text->SetValue( GetString( n ) );
635 }
636#endif
637}
638
639int wxComboBox::FindString(const wxString& s) const
640{
641#if USE_HICOMBOBOX
642 for( int i = 0 ; i < GetCount() ; i++ )
643 {
644 if ( GetString( i ).IsSameAs(s, FALSE) )
645 return i ;
646 }
647 return wxNOT_FOUND ;
648#else
649 return m_choice->FindString( s );
650#endif
651}
652
653wxString wxComboBox::GetString(int n) const
654{
655#if USE_HICOMBOBOX
656 CFStringRef itemText;
657 HIComboBoxCopyTextItemAtIndex( (HIViewRef) m_macControl, (CFIndex)n, &itemText );
658 return wxMacCFStringHolder(itemText).AsString();
659#else
660 return m_choice->GetString( n );
661#endif
662}
663
664wxString wxComboBox::GetStringSelection() const
665{
b310cebd
SC
666#if USE_HICOMBOBOX
667 CFStringRef cfr ;
668 verify_noerr(GetControlData((ControlRef) m_macControl,kHIComboBoxEditTextPart,kControlEditTextCFStringTag,
669 sizeof(CFStringRef),(Ptr) &cfr,NULL));
670 // takes of release responsibility
671 wxMacCFStringHolder cf( cfr ) ;
672 return cf.AsString() ;
673#else
46cc7c4e
SC
674 int sel = GetSelection ();
675 if (sel > -1)
676 return wxString(this->GetString (sel));
677 else
678 return wxEmptyString;
b310cebd 679#endif
46cc7c4e
SC
680}
681
682bool wxComboBox::SetStringSelection(const wxString& sel)
683{
684 int s = FindString (sel);
685 if (s > -1)
686 {
687 SetSelection (s);
688 return TRUE;
689 }
690 else
691 return FALSE;
692}
693
694void wxComboBox::SetString(int n, const wxString& s)
695{
696#if USE_HICOMBOBOX
b310cebd
SC
697 verify_noerr ( HIComboBoxInsertTextItemAtIndex( (HIViewRef) m_macControl, (CFIndex) n,
698 wxMacCFStringHolder(s, m_font.GetEncoding()) ) );
699 verify_noerr ( HIComboBoxRemoveItemAtIndex( (HIViewRef) m_macControl, (CFIndex) n + 1 ) );
46cc7c4e
SC
700#else
701 m_choice->SetString( n , s ) ;
702#endif
703}
704
705
706wxInt32 wxComboBox::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
707{
46cc7c4e
SC
708 wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_SELECTED, m_windowId );
709 event.SetInt(GetSelection());
710 event.SetEventObject(this);
711 event.SetString(GetStringSelection());
712 ProcessCommand(event);
713 return noErr ;
46cc7c4e
SC
714}
715