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