1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/choice.cpp
4 // Author: Stefan Csomor
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
16 #include "wx/choice.h"
18 #include "wx/mac/uma.h"
20 extern MenuHandle
NewUniqueMenu() ;
22 IMPLEMENT_DYNAMIC_CLASS(wxChoice
, wxControl
)
27 if ( HasClientObjectData() )
29 size_t i
, max
= GetCount();
31 for ( i
= 0; i
< max
; ++i
)
32 delete GetClientObject( i
);
35 // DeleteMenu( m_macPopUpMenuId ) ;
36 // DisposeMenu( m_macPopUpMenuHandle ) ;
39 bool wxChoice::Create(wxWindow
*parent
,
43 const wxArrayString
& choices
,
45 const wxValidator
& validator
,
46 const wxString
& name
)
48 wxCArrayString
chs( choices
);
51 parent
, id
, pos
, size
, chs
.GetCount(), chs
.GetStrings(),
52 style
, validator
, name
);
55 bool wxChoice::Create(wxWindow
*parent
,
60 const wxString choices
[],
62 const wxValidator
& validator
,
63 const wxString
& name
)
65 m_macIsUserPane
= false;
67 if ( !wxChoiceBase::Create( parent
, id
, pos
, size
, style
, validator
, name
) )
70 Rect bounds
= wxMacGetBoundsForControl( this , pos
, size
);
72 m_peer
= new wxMacControl( this ) ;
73 OSStatus err
= CreatePopupButtonControl(
74 MAC_WXHWND(parent
->MacGetTopLevelWindowRef()) , &bounds
, CFSTR("") ,
75 -12345 , false /* no variable width */ , 0 , 0 , 0 , m_peer
->GetControlRefAddr() );
78 m_macPopUpMenuHandle
= NewUniqueMenu() ;
79 m_peer
->SetData
<MenuHandle
>( kControlNoPart
, kControlPopupButtonMenuHandleTag
, (MenuHandle
) m_macPopUpMenuHandle
) ;
80 m_peer
->SetValueAndRange( n
> 0 ? 1 : 0 , 0 , 0 );
81 MacPostControlCreate( pos
, size
);
84 if ( style
& wxCB_SORT
)
86 m_strings
= wxArrayString( 1 );
89 for ( int i
= 0; i
< n
; i
++ )
94 // Set the first item as being selected
98 // Needed because it is a wxControlWithItems
104 // ----------------------------------------------------------------------------
105 // adding/deleting items to/from the list
106 // ----------------------------------------------------------------------------
107 int wxChoice::DoAppend( const wxString
& item
)
110 wxArrayString::iterator insertPoint
;
113 if (GetWindowStyle() & wxCB_SORT
)
115 insertPoint
= std::lower_bound( m_strings
.begin(), m_strings
.end(), item
);
116 index
= insertPoint
- m_strings
.begin();
120 insertPoint
= m_strings
.end();
121 index
= m_strings
.size();
124 m_strings
.insert( insertPoint
, item
);
126 size_t index
= m_strings
.Add( item
);
129 m_datas
.Insert( NULL
, index
);
130 UMAInsertMenuItem( MAC_WXHMENU( m_macPopUpMenuHandle
), item
, m_font
.GetEncoding(), index
);
131 DoSetItemClientData( index
, NULL
);
132 m_peer
->SetMaximum( GetCount() );
137 int wxChoice::DoInsert( const wxString
& item
, int pos
)
139 wxCHECK_MSG( !(GetWindowStyle() & wxCB_SORT
), -1, wxT("wxChoice::DoInsert: can't insert into sorted list") );
140 wxCHECK_MSG( (pos
>= 0) && (pos
<= GetCount()), -1, wxT("wxChoice::DoInsert: invalid index") );
142 if (pos
== GetCount())
143 return DoAppend( item
);
145 UMAInsertMenuItem( MAC_WXHMENU( m_macPopUpMenuHandle
), item
, m_font
.GetEncoding(), pos
);
146 m_strings
.Insert( item
, pos
);
147 m_datas
.Insert( NULL
, pos
);
148 DoSetItemClientData( pos
, NULL
);
149 m_peer
->SetMaximum( GetCount() );
154 void wxChoice::Delete( int n
)
156 wxCHECK_RET( n
< GetCount(), wxT("wxChoice::Delete: invalid index") );
158 if ( HasClientObjectData() )
159 delete GetClientObject( n
);
161 ::DeleteMenuItem( MAC_WXHMENU(m_macPopUpMenuHandle
) , n
+ 1 ) ;
162 m_strings
.RemoveAt( n
) ;
163 m_datas
.RemoveAt( n
) ;
164 m_peer
->SetMaximum( GetCount() ) ;
167 void wxChoice::Clear()
170 for ( int i
= 0 ; i
< GetCount() ; i
++ )
172 ::DeleteMenuItem( MAC_WXHMENU(m_macPopUpMenuHandle
) , 1 ) ;
177 m_peer
->SetMaximum( 0 ) ;
180 void wxChoice::FreeData()
182 if ( HasClientObjectData() )
184 size_t count
= GetCount();
185 for ( size_t n
= 0; n
< count
; n
++ )
187 delete GetClientObject( n
);
192 // ----------------------------------------------------------------------------
194 // ----------------------------------------------------------------------------
195 int wxChoice::GetSelection() const
197 return m_peer
->GetValue() - 1 ;
200 void wxChoice::SetSelection( int n
)
202 m_peer
->SetValue( n
+ 1 ) ;
205 // ----------------------------------------------------------------------------
206 // string list functions
207 // ----------------------------------------------------------------------------
209 int wxChoice::GetCount() const
211 return m_strings
.GetCount() ;
214 int wxChoice::FindString( const wxString
& s
, bool bCase
) const
216 return m_strings
.Index( s
, bCase
) ;
219 void wxChoice::SetString( int n
, const wxString
& s
)
221 wxCHECK_RET( n
>= 0 && (size_t)n
< m_strings
.GetCount(),
222 wxT("wxChoice::SetString(): invalid index") );
226 // apple menu pos is 1-based
227 UMASetMenuItemText( MAC_WXHMENU(m_macPopUpMenuHandle
) , n
+ 1 , s
, wxFont::GetDefaultEncoding() ) ;
230 wxString
wxChoice::GetString( int n
) const
232 wxCHECK_MSG( n
>= 0 && (size_t)n
< m_strings
.GetCount(), wxEmptyString
,
233 wxT("wxChoice::GetString(): invalid index") );
235 return m_strings
[n
] ;
238 // ----------------------------------------------------------------------------
240 // ----------------------------------------------------------------------------
241 void wxChoice::DoSetItemClientData( int n
, void* clientData
)
243 wxCHECK_RET( n
>= 0 && (size_t)n
< m_datas
.GetCount(),
244 wxT("wxChoice::DoSetItemClientData: invalid index") );
246 m_datas
[n
] = (char*)clientData
;
249 void * wxChoice::DoGetItemClientData( int n
) const
251 wxCHECK_MSG( n
>= 0 && (size_t)n
< m_datas
.GetCount(), NULL
,
252 wxT("wxChoice::DoGetClientData: invalid index") );
254 return (void *)m_datas
[n
];
257 void wxChoice::DoSetItemClientObject( int n
, wxClientData
* clientData
)
259 DoSetItemClientData( n
, clientData
) ;
262 wxClientData
* wxChoice::DoGetItemClientObject( int n
) const
264 return (wxClientData
*)DoGetItemClientData( n
) ;
267 wxInt32
wxChoice::MacControlHit( WXEVENTHANDLERREF
WXUNUSED(handler
) , WXEVENTREF
WXUNUSED(event
) )
269 wxCommandEvent
event( wxEVT_COMMAND_CHOICE_SELECTED
, m_windowId
);
271 // actually n should be made sure by the os to be a valid selection, but ...
272 int n
= GetSelection();
276 event
.SetString( GetStringSelection() );
277 event
.SetEventObject( this );
279 if ( HasClientObjectData() )
280 event
.SetClientObject( GetClientObject( n
) );
281 else if ( HasClientUntypedData() )
282 event
.SetClientData( GetClientData( n
) );
284 ProcessCommand( event
);
290 wxSize
wxChoice::DoGetBestSize() const
292 int lbWidth
= GetCount() > 0 ? 20 : 100; // some defaults
299 GetThemeMetric( kThemeMetricPopupButtonHeight
, &metric
);
304 wxMacPortStateHelper
st( UMAGetWindowPort( (WindowRef
) MacGetTopLevelWindowRef() ) ) ;
307 ::TextFont( m_font
.MacGetFontNum() ) ;
308 ::TextSize( m_font
.MacGetFontSize() ) ;
309 ::TextFace( m_font
.MacGetFontStyle() ) ;
313 ::TextFont( kFontIDMonaco
) ;
318 // Find the widest line
319 for(int i
= 0; i
< GetCount(); i
++)
321 wxString
str( GetString( i
) );
324 Point bounds
= { 0, 0 } ;
327 ::GetThemeTextDimensions( wxMacCFStringHolder( str
, m_font
.GetEncoding() ) ,
328 kThemeCurrentPortFont
,
336 wLine
= ::TextWidth( str
.c_str() , 0 , str
.Length() ) ;
339 lbWidth
= wxMax( lbWidth
, wLine
) ;
342 // Add room for the popup arrow
343 lbWidth
+= 2 * lbHeight
;
345 // And just a bit more
346 int cx
= ::TextWidth( "X" , 0 , 1 ) ;
350 return wxSize( lbWidth
, lbHeight
);
353 #endif // wxUSE_CHOICE