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