]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/choice.cpp
Explicitly forward non-command events along to the native control first.
[wxWidgets.git] / src / mac / carbon / choice.cpp
CommitLineData
2ac013b1 1/////////////////////////////////////////////////////////////////////////////
11e62fe6 2// Name: src/mac/carbon/choice.cpp
e9576ca5 3// Purpose: wxChoice
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
8228b893 9// Licence: wxWindows licence
e9576ca5 10/////////////////////////////////////////////////////////////////////////////
e40298d5 11
a8e9860d 12#include "wx/wxprec.h"
312ebad4
WS
13
14#if wxUSE_CHOICE
15
e9576ca5 16#include "wx/choice.h"
3b3dc801
WS
17
18#ifndef WX_PRECOMP
19 #include "wx/menu.h"
ad002397 20 #include "wx/dcclient.h"
3b3dc801
WS
21#endif
22
519cb848 23#include "wx/mac/uma.h"
e40298d5 24
d34cca53
DS
25extern MenuHandle NewUniqueMenu() ;
26
e9576ca5 27IMPLEMENT_DYNAMIC_CLASS(wxChoice, wxControl)
e40298d5 28
e40298d5 29
5b781a67
SC
30wxChoice::~wxChoice()
31{
d76240bf
MB
32 if ( HasClientObjectData() )
33 {
aa61d352 34 unsigned int i, max = GetCount();
d76240bf
MB
35
36 for ( i = 0; i < max; ++i )
d34cca53 37 delete GetClientObject( i );
d76240bf
MB
38 }
39
d34cca53 40 // DeleteMenu( m_macPopUpMenuId ) ;
e40298d5 41 // DisposeMenu( m_macPopUpMenuHandle ) ;
5b781a67 42}
e40298d5 43
d34cca53
DS
44bool wxChoice::Create(wxWindow *parent,
45 wxWindowID id,
46 const wxPoint& pos,
47 const wxSize& size,
48 const wxArrayString& choices,
49 long style,
50 const wxValidator& validator,
51 const wxString& name )
584ad2a3 52{
d34cca53 53 wxCArrayString chs( choices );
584ad2a3 54
d34cca53
DS
55 return Create(
56 parent, id, pos, size, chs.GetCount(), chs.GetStrings(),
57 style, validator, name );
584ad2a3
MB
58}
59
d34cca53
DS
60bool wxChoice::Create(wxWindow *parent,
61 wxWindowID id,
62 const wxPoint& pos,
63 const wxSize& size,
64 int n,
65 const wxString choices[],
66 long style,
67 const wxValidator& validator,
68 const wxString& name )
e9576ca5 69{
d34cca53 70 m_macIsUserPane = false;
312ebad4 71
d34cca53 72 if ( !wxChoiceBase::Create( parent, id, pos, size, style, validator, name ) )
b45ed7a2
VZ
73 return false;
74
d34cca53 75 Rect bounds = wxMacGetBoundsForControl( this , pos , size );
4c37f124 76
d34cca53
DS
77 m_peer = new wxMacControl( this ) ;
78 OSStatus err = CreatePopupButtonControl(
79 MAC_WXHWND(parent->MacGetTopLevelWindowRef()) , &bounds , CFSTR("") ,
80 -12345 , false /* no variable width */ , 0 , 0 , 0 , m_peer->GetControlRefAddr() );
81 verify_noerr( err );
312ebad4 82
d34cca53 83 m_macPopUpMenuHandle = NewUniqueMenu() ;
21fd5529 84 m_peer->SetData<MenuHandle>( kControlNoPart , kControlPopupButtonMenuHandleTag , (MenuHandle) m_macPopUpMenuHandle ) ;
d34cca53
DS
85 m_peer->SetValueAndRange( n > 0 ? 1 : 0 , 0 , 0 );
86 MacPostControlCreate( pos, size );
34585919 87
7b6986c3 88#if !wxUSE_STL
34585919 89 if ( style & wxCB_SORT )
d34cca53
DS
90 // autosort
91 m_strings = wxArrayString( 1 );
7b6986c3 92#endif
11e62fe6 93
b668a735
SC
94 for ( int i = 0; i < n; i++ )
95 {
d34cca53 96 Append( choices[i] );
b668a735 97 }
d34cca53
DS
98
99 // Set the first item as being selected
100 if (n > 0)
101 SetSelection( 0 );
102
103 // Needed because it is a wxControlWithItems
170acdc9 104 SetInitialSize( size );
d34cca53 105
312ebad4 106 return true;
e9576ca5 107}
e40298d5 108
b668a735
SC
109// ----------------------------------------------------------------------------
110// adding/deleting items to/from the list
111// ----------------------------------------------------------------------------
d34cca53 112int wxChoice::DoAppend( const wxString& item )
e9576ca5 113{
aacd1442 114#if wxUSE_STL
9c707f80 115 wxArrayString::iterator insertPoint;
aa61d352 116 unsigned int index;
11e62fe6 117
9c707f80
MB
118 if (GetWindowStyle() & wxCB_SORT)
119 {
120 insertPoint = std::lower_bound( m_strings.begin(), m_strings.end(), item );
121 index = insertPoint - m_strings.begin();
122 }
123 else
124 {
125 insertPoint = m_strings.end();
126 index = m_strings.size();
127 }
128
129 m_strings.insert( insertPoint, item );
aacd1442 130#else
aa61d352 131 unsigned int index = m_strings.Add( item );
aacd1442 132#endif
d34cca53
DS
133
134 m_datas.Insert( NULL , index );
135 UMAInsertMenuItem( MAC_WXHMENU( m_macPopUpMenuHandle ), item, m_font.GetEncoding(), index );
136 DoSetItemClientData( index, NULL );
137 m_peer->SetMaximum( GetCount() );
138
139 return index;
2597135a 140}
e40298d5 141
aa61d352 142int wxChoice::DoInsert( const wxString& item, unsigned int pos )
243dbf1a 143{
d34cca53 144 wxCHECK_MSG( !(GetWindowStyle() & wxCB_SORT), -1, wxT("wxChoice::DoInsert: can't insert into sorted list") );
8228b893 145 wxCHECK_MSG( IsValidInsert(pos), -1, wxT("wxChoice::DoInsert: invalid index") );
243dbf1a 146
aa61d352 147 if (pos == GetCount())
d34cca53 148 return DoAppend( item );
243dbf1a 149
d34cca53
DS
150 UMAInsertMenuItem( MAC_WXHMENU( m_macPopUpMenuHandle ), item, m_font.GetEncoding(), pos );
151 m_strings.Insert( item, pos );
152 m_datas.Insert( NULL, pos );
153 DoSetItemClientData( pos, NULL );
154 m_peer->SetMaximum( GetCount() );
155
156 return pos;
243dbf1a
VZ
157}
158
aa61d352 159void wxChoice::Delete(unsigned int n)
2597135a 160{
8228b893 161 wxCHECK_RET( IsValid(n) , wxT("wxChoice::Delete: invalid index") );
d34cca53 162
b668a735 163 if ( HasClientObjectData() )
d34cca53
DS
164 delete GetClientObject( n );
165
166 ::DeleteMenuItem( MAC_WXHMENU(m_macPopUpMenuHandle) , n + 1 ) ;
5fe38474 167 m_strings.RemoveAt( n ) ;
3ef585df 168 m_datas.RemoveAt( n ) ;
21fd5529 169 m_peer->SetMaximum( GetCount() ) ;
e9576ca5 170}
e40298d5 171
e9576ca5
SC
172void wxChoice::Clear()
173{
4b651a46 174 FreeData();
aa61d352 175 for ( unsigned int i = 0 ; i < GetCount() ; i++ )
519cb848 176 {
e40298d5 177 ::DeleteMenuItem( MAC_WXHMENU(m_macPopUpMenuHandle) , 1 ) ;
4b651a46 178 }
d34cca53 179
b668a735
SC
180 m_strings.Empty() ;
181 m_datas.Empty() ;
21fd5529 182 m_peer->SetMaximum( 0 ) ;
e9576ca5 183}
e40298d5 184
4b651a46 185void wxChoice::FreeData()
b668a735
SC
186{
187 if ( HasClientObjectData() )
188 {
aa61d352
VZ
189 unsigned int count = GetCount();
190 for ( unsigned int n = 0; n < count; n++ )
b668a735 191 {
d34cca53 192 delete GetClientObject( n );
b668a735
SC
193 }
194 }
195}
e40298d5 196
b668a735
SC
197// ----------------------------------------------------------------------------
198// selection
199// ----------------------------------------------------------------------------
e9576ca5
SC
200int wxChoice::GetSelection() const
201{
d34cca53 202 return m_peer->GetValue() - 1 ;
e9576ca5 203}
e40298d5 204
d34cca53 205void wxChoice::SetSelection( int n )
519cb848 206{
21fd5529 207 m_peer->SetValue( n + 1 ) ;
519cb848 208}
e40298d5 209
b668a735
SC
210// ----------------------------------------------------------------------------
211// string list functions
212// ----------------------------------------------------------------------------
e40298d5 213
aa61d352 214unsigned int wxChoice::GetCount() const
e9576ca5 215{
b668a735 216 return m_strings.GetCount() ;
e9576ca5 217}
e40298d5 218
d34cca53 219int wxChoice::FindString( const wxString& s, bool bCase ) const
e9576ca5 220{
dd61c39d
JS
221#if !wxUSE_STL
222 // Avoid assert for non-default args passed to sorted array Index
223 if ( HasFlag(wxCB_SORT) )
224 bCase = true;
225#endif
226
11e62fe6 227 return m_strings.Index( s , bCase ) ;
b668a735 228}
e40298d5 229
aa61d352 230void wxChoice::SetString(unsigned int n, const wxString& s)
b668a735 231{
8228b893 232 wxCHECK_RET( IsValid(n), wxT("wxChoice::SetString(): invalid index") );
d34cca53 233
34585919 234 m_strings[n] = s ;
d34cca53 235
34585919
SC
236 // apple menu pos is 1-based
237 UMASetMenuItemText( MAC_WXHMENU(m_macPopUpMenuHandle) , n + 1 , s , wxFont::GetDefaultEncoding() ) ;
e9576ca5
SC
238}
239
aa61d352 240wxString wxChoice::GetString(unsigned int n) const
e9576ca5 241{
8228b893 242 wxCHECK_MSG( IsValid(n), wxEmptyString, wxT("wxChoice::GetString(): invalid index") );
17a6a662 243
e40298d5 244 return m_strings[n] ;
e9576ca5 245}
17a6a662 246
b668a735
SC
247// ----------------------------------------------------------------------------
248// client data
249// ----------------------------------------------------------------------------
aa61d352 250void wxChoice::DoSetItemClientData(unsigned int n, void* clientData)
b668a735 251{
8228b893 252 wxCHECK_RET( IsValid(n), wxT("wxChoice::DoSetItemClientData: invalid index") );
c69279ef 253
d34cca53 254 m_datas[n] = (char*)clientData ;
b668a735 255}
e40298d5 256
aa61d352 257void * wxChoice::DoGetItemClientData(unsigned int n) const
b668a735 258{
8228b893 259 wxCHECK_MSG( IsValid(n), NULL, wxT("wxChoice::DoGetClientData: invalid index") );
d34cca53 260
d81cc883 261 return (void *)m_datas[n];
b668a735 262}
e40298d5 263
aa61d352 264void wxChoice::DoSetItemClientObject(unsigned int n, wxClientData* clientData)
b668a735 265{
aa61d352 266 DoSetItemClientData(n, clientData);
b668a735 267}
e40298d5 268
aa61d352 269wxClientData* wxChoice::DoGetItemClientObject(unsigned int n) const
e9576ca5 270{
d34cca53 271 return (wxClientData*)DoGetItemClientData( n ) ;
e9576ca5 272}
e40298d5 273
d34cca53 274wxInt32 wxChoice::MacControlHit( WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
b668a735 275{
d34cca53
DS
276 wxCommandEvent event( wxEVT_COMMAND_CHOICE_SELECTED, m_windowId );
277
f2d990ad 278 // actually n should be made sure by the os to be a valid selection, but ...
d34cca53 279 int n = GetSelection();
f2d990ad
SC
280 if ( n > -1 )
281 {
282 event.SetInt( n );
d34cca53
DS
283 event.SetString( GetStringSelection() );
284 event.SetEventObject( this );
285
f2d990ad 286 if ( HasClientObjectData() )
d34cca53 287 event.SetClientObject( GetClientObject( n ) );
f2d990ad 288 else if ( HasClientUntypedData() )
d34cca53
DS
289 event.SetClientData( GetClientData( n ) );
290
291 ProcessCommand( event );
f2d990ad 292 }
d34cca53 293
4c37f124 294 return noErr ;
9453cf2b 295}
e40298d5 296
f2d990ad 297wxSize wxChoice::DoGetBestSize() const
b668a735 298{
637988a4 299 int lbWidth = GetCount() > 0 ? 20 : 100; // some defaults
f2d990ad
SC
300 int lbHeight = 20;
301 int wLine;
d34cca53 302
f2d990ad 303#if TARGET_CARBON
7cd7bc23 304 SInt32 metric ;
d34cca53
DS
305
306 GetThemeMetric( kThemeMetricPopupButtonHeight , &metric );
c69279ef 307 lbHeight = metric ;
f2d990ad 308#endif
d34cca53 309
e40298d5 310 {
7cd7bc23
SC
311#if wxMAC_USE_CORE_GRAPHICS
312 wxClientDC dc(const_cast<wxChoice*>(this));
313#else
facd6764 314 wxMacPortStateHelper st( UMAGetWindowPort( (WindowRef) MacGetTopLevelWindowRef() ) ) ;
fcb35beb 315 if ( m_font.Ok() )
e40298d5 316 {
facd6764
SC
317 ::TextFont( m_font.MacGetFontNum() ) ;
318 ::TextSize( m_font.MacGetFontSize() ) ;
319 ::TextFace( m_font.MacGetFontStyle() ) ;
e40298d5
JS
320 }
321 else
322 {
323 ::TextFont( kFontIDMonaco ) ;
d34cca53 324 ::TextSize( 9 ) ;
e40298d5
JS
325 ::TextFace( 0 ) ;
326 }
7cd7bc23 327#endif
e40298d5 328 // Find the widest line
aa61d352 329 for(unsigned int i = 0; i < GetCount(); i++)
d34cca53 330 {
aa61d352 331 wxString str(GetString(i));
7cd7bc23
SC
332#if wxMAC_USE_CORE_GRAPHICS
333 wxCoord width, height ;
334 dc.GetTextExtent( str , &width, &height);
335 wLine = width ;
336#else
d34cca53
DS
337#if wxUSE_UNICODE
338 Point bounds = { 0, 0 } ;
2c1a3312 339 SInt16 baseline ;
d34cca53 340
a9412f8f 341 ::GetThemeTextDimensions( wxMacCFStringHolder( str , m_font.GetEncoding() ) ,
2c1a3312
SC
342 kThemeCurrentPortFont,
343 kThemeStateActive,
344 false,
345 &bounds,
346 &baseline );
d34cca53 347
2c1a3312 348 wLine = bounds.h ;
d34cca53 349#else
8228b893 350 wLine = ::TextWidth( str.c_str() , 0 , str.length() ) ;
d34cca53 351#endif
7cd7bc23 352#endif
d34cca53 353 lbWidth = wxMax( lbWidth, wLine ) ;
e40298d5 354 }
d34cca53 355
e40298d5
JS
356 // Add room for the popup arrow
357 lbWidth += 2 * lbHeight ;
7cd7bc23
SC
358#if wxMAC_USE_CORE_GRAPHICS
359 wxCoord width, height ;
360 dc.GetTextExtent( wxT("X"), &width, &height);
361 int cx = width ;
362#else
e40298d5 363 // And just a bit more
e40298d5 364 int cx = ::TextWidth( "X" , 0 , 1 ) ;
7cd7bc23 365#endif
e40298d5 366 lbWidth += cx ;
e40298d5 367 }
d34cca53
DS
368
369 return wxSize( lbWidth, lbHeight );
d76240bf 370}
312ebad4
WS
371
372#endif // wxUSE_CHOICE