]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/mac/carbon/choice.cpp
cleanup:
[wxWidgets.git] / src / mac / carbon / choice.cpp
... / ...
CommitLineData
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
25extern MenuHandle NewUniqueMenu() ;
26
27IMPLEMENT_DYNAMIC_CLASS(wxChoice, wxControl)
28
29
30wxChoice::~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
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 )
52{
53 wxCArrayString chs( choices );
54
55 return Create(
56 parent, id, pos, size, chs.GetCount(), chs.GetStrings(),
57 style, validator, name );
58}
59
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 )
69{
70 m_macIsUserPane = false;
71
72 if ( !wxChoiceBase::Create( parent, id, pos, size, style, validator, name ) )
73 return false;
74
75 Rect bounds = wxMacGetBoundsForControl( this , pos , size );
76
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 );
82
83 m_macPopUpMenuHandle = NewUniqueMenu() ;
84 m_peer->SetData<MenuHandle>( kControlNoPart , kControlPopupButtonMenuHandleTag , (MenuHandle) m_macPopUpMenuHandle ) ;
85 m_peer->SetValueAndRange( n > 0 ? 1 : 0 , 0 , 0 );
86 MacPostControlCreate( pos, size );
87
88#if !wxUSE_STL
89 if ( style & wxCB_SORT )
90 // autosort
91 m_strings = wxArrayString( 1 );
92#endif
93
94 for ( int i = 0; i < n; i++ )
95 {
96 Append( choices[i] );
97 }
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// ----------------------------------------------------------------------------
112int wxChoice::DoAppend( const wxString& item )
113{
114#if wxUSE_STL
115 wxArrayString::iterator insertPoint;
116 unsigned int index;
117
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 );
130#else
131 unsigned int index = m_strings.Add( item );
132#endif
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;
140}
141
142int wxChoice::DoInsert( const wxString& item, unsigned int pos )
143{
144 wxCHECK_MSG( !(GetWindowStyle() & wxCB_SORT), -1, wxT("wxChoice::DoInsert: can't insert into sorted list") );
145 wxCHECK_MSG( IsValidInsert(pos), -1, wxT("wxChoice::DoInsert: invalid index") );
146
147 if (pos == GetCount())
148 return DoAppend( item );
149
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;
157}
158
159void wxChoice::Delete(unsigned int n)
160{
161 wxCHECK_RET( IsValid(n) , wxT("wxChoice::Delete: invalid index") );
162
163 if ( HasClientObjectData() )
164 delete GetClientObject( n );
165
166 ::DeleteMenuItem( MAC_WXHMENU(m_macPopUpMenuHandle) , n + 1 ) ;
167 m_strings.RemoveAt( n ) ;
168 m_datas.RemoveAt( n ) ;
169 m_peer->SetMaximum( GetCount() ) ;
170}
171
172void wxChoice::Clear()
173{
174 FreeData();
175 for ( unsigned int i = 0 ; i < GetCount() ; i++ )
176 {
177 ::DeleteMenuItem( MAC_WXHMENU(m_macPopUpMenuHandle) , 1 ) ;
178 }
179
180 m_strings.Empty() ;
181 m_datas.Empty() ;
182 m_peer->SetMaximum( 0 ) ;
183}
184
185void wxChoice::FreeData()
186{
187 if ( HasClientObjectData() )
188 {
189 unsigned int count = GetCount();
190 for ( unsigned int n = 0; n < count; n++ )
191 {
192 delete GetClientObject( n );
193 }
194 }
195}
196
197// ----------------------------------------------------------------------------
198// selection
199// ----------------------------------------------------------------------------
200int wxChoice::GetSelection() const
201{
202 return m_peer->GetValue() - 1 ;
203}
204
205void wxChoice::SetSelection( int n )
206{
207 m_peer->SetValue( n + 1 ) ;
208}
209
210// ----------------------------------------------------------------------------
211// string list functions
212// ----------------------------------------------------------------------------
213
214unsigned int wxChoice::GetCount() const
215{
216 return m_strings.GetCount() ;
217}
218
219int wxChoice::FindString( const wxString& s, bool bCase ) const
220{
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
227 return m_strings.Index( s , bCase ) ;
228}
229
230void wxChoice::SetString(unsigned int n, const wxString& s)
231{
232 wxCHECK_RET( IsValid(n), wxT("wxChoice::SetString(): invalid index") );
233
234 m_strings[n] = s ;
235
236 // apple menu pos is 1-based
237 UMASetMenuItemText( MAC_WXHMENU(m_macPopUpMenuHandle) , n + 1 , s , wxFont::GetDefaultEncoding() ) ;
238}
239
240wxString wxChoice::GetString(unsigned int n) const
241{
242 wxCHECK_MSG( IsValid(n), wxEmptyString, wxT("wxChoice::GetString(): invalid index") );
243
244 return m_strings[n] ;
245}
246
247// ----------------------------------------------------------------------------
248// client data
249// ----------------------------------------------------------------------------
250void wxChoice::DoSetItemClientData(unsigned int n, void* clientData)
251{
252 wxCHECK_RET( IsValid(n), wxT("wxChoice::DoSetItemClientData: invalid index") );
253
254 m_datas[n] = (char*)clientData ;
255}
256
257void * wxChoice::DoGetItemClientData(unsigned int n) const
258{
259 wxCHECK_MSG( IsValid(n), NULL, wxT("wxChoice::DoGetClientData: invalid index") );
260
261 return (void *)m_datas[n];
262}
263
264void wxChoice::DoSetItemClientObject(unsigned int n, wxClientData* clientData)
265{
266 DoSetItemClientData(n, clientData);
267}
268
269wxClientData* wxChoice::DoGetItemClientObject(unsigned int n) const
270{
271 return (wxClientData*)DoGetItemClientData( n ) ;
272}
273
274wxInt32 wxChoice::MacControlHit( WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
275{
276 wxCommandEvent event( wxEVT_COMMAND_CHOICE_SELECTED, m_windowId );
277
278 // actually n should be made sure by the os to be a valid selection, but ...
279 int n = GetSelection();
280 if ( n > -1 )
281 {
282 event.SetInt( n );
283 event.SetString( GetStringSelection() );
284 event.SetEventObject( this );
285
286 if ( HasClientObjectData() )
287 event.SetClientObject( GetClientObject( n ) );
288 else if ( HasClientUntypedData() )
289 event.SetClientData( GetClientData( n ) );
290
291 ProcessCommand( event );
292 }
293
294 return noErr ;
295}
296
297wxSize wxChoice::DoGetBestSize() const
298{
299 int lbWidth = GetCount() > 0 ? 20 : 100; // some defaults
300 int lbHeight = 20;
301 int wLine;
302
303#if TARGET_CARBON
304 SInt32 metric ;
305
306 GetThemeMetric( kThemeMetricPopupButtonHeight , &metric );
307 lbHeight = metric ;
308#endif
309
310 {
311#if wxMAC_USE_CORE_GRAPHICS
312 wxClientDC dc(const_cast<wxChoice*>(this));
313#else
314 wxMacPortStateHelper st( UMAGetWindowPort( (WindowRef) MacGetTopLevelWindowRef() ) ) ;
315 if ( m_font.Ok() )
316 {
317 ::TextFont( m_font.MacGetFontNum() ) ;
318 ::TextSize( m_font.MacGetFontSize() ) ;
319 ::TextFace( m_font.MacGetFontStyle() ) ;
320 }
321 else
322 {
323 ::TextFont( kFontIDMonaco ) ;
324 ::TextSize( 9 ) ;
325 ::TextFace( 0 ) ;
326 }
327#endif
328 // Find the widest line
329 for(unsigned int i = 0; i < GetCount(); i++)
330 {
331 wxString str(GetString(i));
332#if wxMAC_USE_CORE_GRAPHICS
333 wxCoord width, height ;
334 dc.GetTextExtent( str , &width, &height);
335 wLine = width ;
336#else
337#if wxUSE_UNICODE
338 Point bounds = { 0, 0 } ;
339 SInt16 baseline ;
340
341 ::GetThemeTextDimensions( wxMacCFStringHolder( str , m_font.GetEncoding() ) ,
342 kThemeCurrentPortFont,
343 kThemeStateActive,
344 false,
345 &bounds,
346 &baseline );
347
348 wLine = bounds.h ;
349#else
350 wLine = ::TextWidth( str.c_str() , 0 , str.length() ) ;
351#endif
352#endif
353 lbWidth = wxMax( lbWidth, wLine ) ;
354 }
355
356 // Add room for the popup arrow
357 lbWidth += 2 * lbHeight ;
358#if wxMAC_USE_CORE_GRAPHICS
359 wxCoord width, height ;
360 dc.GetTextExtent( wxT("X"), &width, &height);
361 int cx = width ;
362 lbHeight += 4;
363#else
364 // And just a bit more
365 int cx = ::TextWidth( "X" , 0 , 1 ) ;
366#endif
367 lbWidth += cx ;
368 }
369
370 return wxSize( lbWidth, lbHeight );
371}
372
373#endif // wxUSE_CHOICE