]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/choice.cpp
hack around a UnicodeEditTextControl which does not deliver a correct selection unles...
[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{
11e62fe6 220 return m_strings.Index( s , bCase ) ;
b668a735 221}
e40298d5 222
aa61d352 223void wxChoice::SetString(unsigned int n, const wxString& s)
b668a735 224{
8228b893 225 wxCHECK_RET( IsValid(n), wxT("wxChoice::SetString(): invalid index") );
d34cca53 226
34585919 227 m_strings[n] = s ;
d34cca53 228
34585919
SC
229 // apple menu pos is 1-based
230 UMASetMenuItemText( MAC_WXHMENU(m_macPopUpMenuHandle) , n + 1 , s , wxFont::GetDefaultEncoding() ) ;
e9576ca5
SC
231}
232
aa61d352 233wxString wxChoice::GetString(unsigned int n) const
e9576ca5 234{
8228b893 235 wxCHECK_MSG( IsValid(n), wxEmptyString, wxT("wxChoice::GetString(): invalid index") );
17a6a662 236
e40298d5 237 return m_strings[n] ;
e9576ca5 238}
17a6a662 239
b668a735
SC
240// ----------------------------------------------------------------------------
241// client data
242// ----------------------------------------------------------------------------
aa61d352 243void wxChoice::DoSetItemClientData(unsigned int n, void* clientData)
b668a735 244{
8228b893 245 wxCHECK_RET( IsValid(n), wxT("wxChoice::DoSetItemClientData: invalid index") );
c69279ef 246
d34cca53 247 m_datas[n] = (char*)clientData ;
b668a735 248}
e40298d5 249
aa61d352 250void * wxChoice::DoGetItemClientData(unsigned int n) const
b668a735 251{
8228b893 252 wxCHECK_MSG( IsValid(n), NULL, wxT("wxChoice::DoGetClientData: invalid index") );
d34cca53 253
d81cc883 254 return (void *)m_datas[n];
b668a735 255}
e40298d5 256
aa61d352 257void wxChoice::DoSetItemClientObject(unsigned int n, wxClientData* clientData)
b668a735 258{
aa61d352 259 DoSetItemClientData(n, clientData);
b668a735 260}
e40298d5 261
aa61d352 262wxClientData* wxChoice::DoGetItemClientObject(unsigned int n) const
e9576ca5 263{
d34cca53 264 return (wxClientData*)DoGetItemClientData( n ) ;
e9576ca5 265}
e40298d5 266
d34cca53 267wxInt32 wxChoice::MacControlHit( WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
b668a735 268{
d34cca53
DS
269 wxCommandEvent event( wxEVT_COMMAND_CHOICE_SELECTED, m_windowId );
270
f2d990ad 271 // actually n should be made sure by the os to be a valid selection, but ...
d34cca53 272 int n = GetSelection();
f2d990ad
SC
273 if ( n > -1 )
274 {
275 event.SetInt( n );
d34cca53
DS
276 event.SetString( GetStringSelection() );
277 event.SetEventObject( this );
278
f2d990ad 279 if ( HasClientObjectData() )
d34cca53 280 event.SetClientObject( GetClientObject( n ) );
f2d990ad 281 else if ( HasClientUntypedData() )
d34cca53
DS
282 event.SetClientData( GetClientData( n ) );
283
284 ProcessCommand( event );
f2d990ad 285 }
d34cca53 286
4c37f124 287 return noErr ;
9453cf2b 288}
e40298d5 289
f2d990ad 290wxSize wxChoice::DoGetBestSize() const
b668a735 291{
637988a4 292 int lbWidth = GetCount() > 0 ? 20 : 100; // some defaults
f2d990ad
SC
293 int lbHeight = 20;
294 int wLine;
d34cca53 295
f2d990ad
SC
296#if TARGET_CARBON
297 long metric ;
d34cca53
DS
298
299 GetThemeMetric( kThemeMetricPopupButtonHeight , &metric );
c69279ef 300 lbHeight = metric ;
f2d990ad 301#endif
d34cca53 302
e40298d5 303 {
facd6764 304 wxMacPortStateHelper st( UMAGetWindowPort( (WindowRef) MacGetTopLevelWindowRef() ) ) ;
fcb35beb 305 if ( m_font.Ok() )
e40298d5 306 {
facd6764
SC
307 ::TextFont( m_font.MacGetFontNum() ) ;
308 ::TextSize( m_font.MacGetFontSize() ) ;
309 ::TextFace( m_font.MacGetFontStyle() ) ;
e40298d5
JS
310 }
311 else
312 {
313 ::TextFont( kFontIDMonaco ) ;
d34cca53 314 ::TextSize( 9 ) ;
e40298d5
JS
315 ::TextFace( 0 ) ;
316 }
d34cca53 317
e40298d5 318 // Find the widest line
aa61d352 319 for(unsigned int i = 0; i < GetCount(); i++)
d34cca53 320 {
aa61d352 321 wxString str(GetString(i));
d34cca53
DS
322
323#if wxUSE_UNICODE
324 Point bounds = { 0, 0 } ;
2c1a3312 325 SInt16 baseline ;
d34cca53 326
a9412f8f 327 ::GetThemeTextDimensions( wxMacCFStringHolder( str , m_font.GetEncoding() ) ,
2c1a3312
SC
328 kThemeCurrentPortFont,
329 kThemeStateActive,
330 false,
331 &bounds,
332 &baseline );
d34cca53 333
2c1a3312 334 wLine = bounds.h ;
d34cca53 335#else
8228b893 336 wLine = ::TextWidth( str.c_str() , 0 , str.length() ) ;
d34cca53
DS
337#endif
338
339 lbWidth = wxMax( lbWidth, wLine ) ;
e40298d5 340 }
d34cca53 341
e40298d5
JS
342 // Add room for the popup arrow
343 lbWidth += 2 * lbHeight ;
d34cca53 344
e40298d5 345 // And just a bit more
e40298d5
JS
346 int cx = ::TextWidth( "X" , 0 , 1 ) ;
347 lbWidth += cx ;
e40298d5 348 }
d34cca53
DS
349
350 return wxSize( lbWidth, lbHeight );
d76240bf 351}
312ebad4
WS
352
353#endif // wxUSE_CHOICE