]> git.saurik.com Git - wxWidgets.git/blob - src/osx/carbon/choice.cpp
use a single wxBookCtrlEvent class for all wxBookCtrlBase-derived controls (#9667)
[wxWidgets.git] / src / osx / 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/osx/uma.h"
24
25 extern MenuHandle NewUniqueMenu() ;
26
27 IMPLEMENT_DYNAMIC_CLASS(wxChoice, wxControlWithItems)
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 if ( !Create( parent, id, pos, size, 0, NULL, style, validator, name ) )
54 return false;
55
56 Append( choices );
57
58 if ( !choices.empty() )
59 SetSelection( 0 );
60
61 SetInitialSize( size );
62
63 return true;
64 }
65
66 bool wxChoice::Create(wxWindow *parent,
67 wxWindowID id,
68 const wxPoint& pos,
69 const wxSize& size,
70 int n,
71 const wxString choices[],
72 long style,
73 const wxValidator& validator,
74 const wxString& name )
75 {
76 m_macIsUserPane = false;
77
78 if ( !wxChoiceBase::Create( parent, id, pos, size, style, validator, name ) )
79 return false;
80
81 Rect bounds = wxMacGetBoundsForControl( this , pos , size );
82
83 m_peer = new wxMacControl( this ) ;
84 OSStatus err = CreatePopupButtonControl(
85 MAC_WXHWND(parent->MacGetTopLevelWindowRef()) , &bounds , CFSTR("") ,
86 -12345 , false /* no variable width */ , 0 , 0 , 0 , m_peer->GetControlRefAddr() );
87 verify_noerr( err );
88
89 m_macPopUpMenuHandle = NewUniqueMenu() ;
90 m_peer->SetData<MenuHandle>( kControlNoPart , kControlPopupButtonMenuHandleTag , (MenuHandle) m_macPopUpMenuHandle ) ;
91 m_peer->SetValueAndRange( n > 0 ? 1 : 0 , 0 , 0 );
92 MacPostControlCreate( pos, size );
93
94 #if !wxUSE_STL
95 if ( style & wxCB_SORT )
96 // autosort
97 m_strings = wxArrayString( 1 );
98 #endif
99
100 Append(n, choices);
101
102 // Set the first item as being selected
103 if (n > 0)
104 SetSelection( 0 );
105
106 // Needed because it is a wxControlWithItems
107 SetInitialSize( size );
108
109 return true;
110 }
111
112 // ----------------------------------------------------------------------------
113 // adding/deleting items to/from the list
114 // ----------------------------------------------------------------------------
115
116 int wxChoice::DoInsertItems(const wxArrayStringsAdapter & items,
117 unsigned int pos,
118 void **clientData, wxClientDataType type)
119 {
120 const unsigned int numItems = items.GetCount();
121 for( unsigned int i = 0; i < numItems; ++i, ++pos )
122 {
123 unsigned int idx;
124
125 #if wxUSE_STL
126 if ( IsSorted() )
127 {
128 wxArrayString::iterator
129 insertPoint = std::lower_bound( m_strings.begin(), m_strings.end(), items[i] );
130 idx = insertPoint - m_strings.begin();
131 m_strings.insert( insertPoint, items[i] );
132 }
133 else
134 #endif // wxUSE_STL
135 {
136 idx = pos;
137 m_strings.Insert( items[i], idx );
138 }
139
140 UMAInsertMenuItem(MAC_WXHMENU( m_macPopUpMenuHandle ),
141 items[i],
142 GetFont().GetEncoding(),
143 idx);
144 m_datas.Insert( NULL, idx );
145 AssignNewItemClientData(idx, clientData, i, type);
146 }
147
148 m_peer->SetMaximum( GetCount() );
149
150 return pos - 1;
151 }
152
153 void wxChoice::DoDeleteOneItem(unsigned int n)
154 {
155 wxCHECK_RET( IsValid(n) , wxT("wxChoice::Delete: invalid index") );
156
157 if ( HasClientObjectData() )
158 delete GetClientObject( n );
159
160 ::DeleteMenuItem( MAC_WXHMENU(m_macPopUpMenuHandle) , n + 1 ) ;
161 m_strings.RemoveAt( n ) ;
162 m_datas.RemoveAt( n ) ;
163 m_peer->SetMaximum( GetCount() ) ;
164 }
165
166 void wxChoice::DoClear()
167 {
168 for ( unsigned int i = 0 ; i < GetCount() ; i++ )
169 {
170 ::DeleteMenuItem( MAC_WXHMENU(m_macPopUpMenuHandle) , 1 ) ;
171 }
172
173 m_strings.Empty() ;
174 m_datas.Empty() ;
175 m_peer->SetMaximum( 0 ) ;
176 }
177
178 // ----------------------------------------------------------------------------
179 // selection
180 // ----------------------------------------------------------------------------
181 int wxChoice::GetSelection() const
182 {
183 return m_peer->GetValue() - 1 ;
184 }
185
186 void wxChoice::SetSelection( int n )
187 {
188 m_peer->SetValue( n + 1 ) ;
189 }
190
191 // ----------------------------------------------------------------------------
192 // string list functions
193 // ----------------------------------------------------------------------------
194
195 unsigned int wxChoice::GetCount() const
196 {
197 return m_strings.GetCount() ;
198 }
199
200 int wxChoice::FindString( const wxString& s, bool bCase ) const
201 {
202 #if !wxUSE_STL
203 // Avoid assert for non-default args passed to sorted array Index
204 if ( IsSorted() )
205 bCase = true;
206 #endif
207
208 return m_strings.Index( s , bCase ) ;
209 }
210
211 void wxChoice::SetString(unsigned int n, const wxString& s)
212 {
213 wxCHECK_RET( IsValid(n), wxT("wxChoice::SetString(): invalid index") );
214
215 m_strings[n] = s ;
216
217 // apple menu pos is 1-based
218 UMASetMenuItemText( MAC_WXHMENU(m_macPopUpMenuHandle) , n + 1 , s , wxFont::GetDefaultEncoding() ) ;
219 }
220
221 wxString wxChoice::GetString(unsigned int n) const
222 {
223 wxCHECK_MSG( IsValid(n), wxEmptyString, wxT("wxChoice::GetString(): invalid index") );
224
225 return m_strings[n] ;
226 }
227
228 // ----------------------------------------------------------------------------
229 // client data
230 // ----------------------------------------------------------------------------
231 void wxChoice::DoSetItemClientData(unsigned int n, void* clientData)
232 {
233 wxCHECK_RET( IsValid(n), wxT("wxChoice::DoSetItemClientData: invalid index") );
234
235 m_datas[n] = (char*)clientData ;
236 }
237
238 void * wxChoice::DoGetItemClientData(unsigned int n) const
239 {
240 wxCHECK_MSG( IsValid(n), NULL, wxT("wxChoice::DoGetClientData: invalid index") );
241
242 return (void *)m_datas[n];
243 }
244
245 wxInt32 wxChoice::MacControlHit( WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
246 {
247 wxCommandEvent event( wxEVT_COMMAND_CHOICE_SELECTED, m_windowId );
248
249 // actually n should be made sure by the os to be a valid selection, but ...
250 int n = GetSelection();
251 if ( n > -1 )
252 {
253 event.SetInt( n );
254 event.SetString( GetStringSelection() );
255 event.SetEventObject( this );
256
257 if ( HasClientObjectData() )
258 event.SetClientObject( GetClientObject( n ) );
259 else if ( HasClientUntypedData() )
260 event.SetClientData( GetClientData( n ) );
261
262 ProcessCommand( event );
263 }
264
265 return noErr ;
266 }
267
268 wxSize wxChoice::DoGetBestSize() const
269 {
270 int lbWidth = GetCount() > 0 ? 20 : 100; // some defaults
271 int lbHeight = 20;
272 int wLine;
273
274 SInt32 metric ;
275
276 GetThemeMetric( kThemeMetricPopupButtonHeight , &metric );
277 lbHeight = metric ;
278
279 {
280 wxClientDC dc(const_cast<wxChoice*>(this));
281
282 // Find the widest line
283 for(unsigned int i = 0; i < GetCount(); i++)
284 {
285 wxString str(GetString(i));
286
287 wxCoord width, height ;
288 dc.GetTextExtent( str , &width, &height);
289 wLine = width ;
290
291 lbWidth = wxMax( lbWidth, wLine ) ;
292 }
293
294 // Add room for the popup arrow
295 lbWidth += 2 * lbHeight ;
296
297 wxCoord width, height ;
298 dc.GetTextExtent( wxT("X"), &width, &height);
299 int cx = width ;
300 lbHeight += 4;
301
302 lbWidth += cx ;
303 }
304
305 return wxSize( lbWidth, lbHeight );
306 }
307
308 #endif // wxUSE_CHOICE